基于 Python 和 Selenium 的 铁路12306 自动化购票全解析_selenium 12306 python
一、背景与技术选型
12306 作为全球最大的实时票务系统,日均处理数千万次请求,其反爬机制也在不断升级。有这还怕平时回家买不到票?本文将介绍如何通过 Python 和 Selenium 实现自动化购票,重点突破以下技术难点:
- 反检测配置(隐藏自动化特征)
- 动态元素处理(显式等待与动态定位)
- 多场景交互(登录、查询、预订)
二、核心代码解析
1. 反检测配置(关键反爬策略)
options = Options()# 移除自动化标识options.add_experimental_option(\'excludeSwitches\', [\'enable-automation\'])options.add_argument(\'--disable-blink-features=AutomationsControlled\')# 关闭证书验证options.add_argument(\'ignore-certificate-errors\')driver = webdriver.Chrome(options=options)
- 技术原理:通过修改浏览器启动参数,移除
navigator.webdriver
属性等自动化特征,降低被 12306 识别的概率。
2. 登录模块(用户输入与二次验证)
def Longin(): driver.get(\'https://kyfw.12306.cn/otn/resources/login.html\') user = input(\"请输入用户名: \") pwd = getpass.getpass(\"请输入密码: \") # 密码输入隐藏 # 定位并输入用户名/密码 nameuser = driver.find_element(By.XPATH, \'//div/input[@id=\"J-userName\"]\') password = driver.find_element(By.XPATH, \'//div/input[@id=\"J-password\"]\') nameuser.send_keys(user) password.send_keys(pwd) driver.find_element(By.XPATH, \'//*[@id=\"J-login\"]\').click() # 二次验证(身份证后四位+短信验证码) code_id = input(\"请输入身份证后四位:\") driver.find_element(By.XPATH, \'//*[@id=\"verification_code\"]\').click() code = input(\"请输入验证码:\") driver.find_element(By.XPATH, \'//*[@id=\"code\"]\').send_keys(code) # 检查登录结果 try: error_element = driver.find_element(By.XPATH, \'//*[@id=\"message\"]/p\') if error_element.text == \"用户名或密码错误\": print(\"登录失败:请检查信息\") else: print(\"登录成功\") driver.find_element(By.XPATH, \'//*[@id=\"link_for_ticket\"]\').click() Inquirer() except Exception as e: print(f\"未找到错误提示:{e}\")
- 安全设计:使用
getpass
模块隐藏密码输入,避免敏感信息泄露。 - 验证流程:支持身份证后四位 + 短信验证码的二次验证,符合 12306 最新登录逻辑。
- 运行结果展示
-
请输入用户名: 13800138000请输入密码: ········ # 输入时密码不可见请输入身份证后四位:1234验证码正在发送中,请耐心等待请输入验证码:56789登录成功
3. 查询模块(日期处理与车次提取)
def Inquirer(): chufadi = input(\"请输入出发地:\") mudidi = input(\"请输入目的地:\") # 日期处理(默认当天,支持格式验证) current_date = datetime.now().strftime(\"%Y-%m-%d\") user_input = input(\"输入出发日期(格式: YYYY-MM-DD,留空默认今日):\") departure_date = current_date if not user_input else datetime.strptime(user_input, \"%Y-%m-%d\").strftime(\"%Y-%m-%d\") # 更新日期输入框 if departure_date != current_date: date_input = driver.find_element(By.XPATH, \'//*[@id=\"train_date\"]\') date_input.clear() date_input.send_keys(departure_date) # 点击查询 driver.find_element(By.XPATH, \'//*[@id=\"query_ticket\"]\').click() # 提取车次信息(存在索引越界风险,需优化) list_Train = [] for trin in range(20): try: dizhi = driver.find_element(By.XPATH, f\'//*[@id=\"train_num_{trin}\"]/div/strong\') list_Train.append(dizhi.text) print(f\"车次: {list_Train[trin]} | 出发地: {list_Train[trin+1]} | 到达时间: {list_Train[trin+2]}\") except: break
- 日期验证:使用
datetime.strptime
进行格式校验,确保输入合法。 - 车次提取:通过循环遍历车次列表,动态获取车次信息(需注意索引越界问题)
- 运行结果
-
请输入出发地:北京请输入目的地:上海输入出发日期(格式: YYYY-MM-DD,留空默认今日):2025-05-20正在查询2025-05-20的车票,请稍后... 出发地 目的地 到达时间 G1 北京南 上海虹桥 08:00 出发地 目的地 到达时间 G3 北京南 上海虹桥 09:00 出发地 目的地 到达时间 G5 北京南 上海虹桥 10:00
4. 预订模块(时间匹配与订单提交)
def Get_ticket(): # 提取所有车次的出发时间 time_list = [driver.find_element(By.XPATH, f\'//*[@id=\"train_num_{i}\"]/div[3]/strong[1]\').text for i in range(int(driver.find_element(By.XPATH, \'//*[@id=\"trainum\"]\').text))] move_time = input(\"选择出发时间段(1/2/3):\") wait = WebDriverWait(driver, 10) if move_time == \'1\': driver.find_element(By.XPATH, \'//*[@id=\"cc_start_time\"]/option[3]\').click() accurate_time = input(\"输入目标时间(如12:00):\") closest = get_closest_time(accurate_time, time_list) # 显式等待确保预订按钮可见 wait.until(EC.visibility_of_element_located((By.XPATH, f\'//a[@class=\"btn72\" and contains(text(), \"{closest}\")]\'))) driver.find_element(By.XPATH, f\'//a[@class=\"btn72\" and contains(@onclick, \"{closest}\")]\').click() # 提交订单 driver.find_element(By.XPATH, \'//*[@id=\"normalPassenger_0\"]\').click() # 选择乘客 driver.find_element(By.XPATH, \'//*[@id=\"submitOrder_id\"]\').click() # 提交订单
- 时间匹配:使用
get_closest_time
函数计算最接近用户指定时间的车次,提升购票精准度。 - 显式等待:通过
WebDriverWait
确保预订按钮加载完成,避免元素未找到错误。 - 运行结果展示
-
请输入出发时间段,1: 06:00--12:002: 12:00--18:003: 18:00--24:001输入准确时间,将会自动购买靠近该时间的车票(12:00)09:30最接近 09:30 的时间是: 09:00所有时间为 [\'08:00\', \'09:00\', \'10:00\']
三、代码优化与最佳实践
1. 反检测增强(应对 12306 最新策略)
# 通过CDP命令修改navigator.webdriver属性driver.execute_cdp_cmd(\"Page.addScriptToEvaluateOnNewDocument\", { \"source\": \"\"\" Object.defineProperty(navigator, \'webdriver\', { get: () => undefined }) \"\"\"})
- 技术原理:直接修改浏览器环境,隐藏
navigator.webdriver
属性,绕过 12306 的自动化检测。
2. 动态元素处理(避免固定索引)
# 优化车次信息提取(使用动态定位)trains = driver.find_elements(By.XPATH, \'//div[contains(@id, \"train_num_\")]\')for train in trains: try: info = [elem.text for elem in train.find_elements(By.XPATH, \'./div/strong\')] print(f\"车次: {info[0]} | 出发地: {info[1]} | 到达时间: {info[2]}\") except IndexError: continue
- 优化点:使用动态元素定位,避免固定索引导致的越界错误。
3. 异常处理(提升稳定性)
# 添加异常捕获与重试机制from selenium.common.exceptions import NoSuchElementExceptiondef safe_click(by, value, timeout=10): try: wait = WebDriverWait(driver, timeout) element = wait.until(EC.element_to_be_clickable((by, value))) element.click() except NoSuchElementException: print(f\"元素 {value} 未找到\") except TimeoutException: print(f\"等待元素 {value} 超时\")
- 作用:封装点击操作,处理元素未找到或超时异常,提高脚本鲁棒性。
四、风险提示与合规建议
-
法律风险:
- 自动化抢票可能违反 12306 用户协议,甚至涉嫌非法经营罪。
- 建议仅用于学习用途,避免用于实际购票。
-
账号安全:
- 频繁自动化操作可能导致账号被封禁。
- 避免在代码中存储敏感信息,如账号密码。
-
技术对抗:
- 12306 已推出防抢票专利,如 SVG 验证码、行为验证等。
- 脚本需持续更新以应对反爬策略变化。
五、总结与扩展
本文介绍了基于 Selenium 的 12306 自动化购票实现,涵盖反检测配置、登录验证、车次查询、时间匹配等核心功能。建议结合以下方向进一步优化:
- 多线程与分布式:使用多线程提高查询效率,结合代理 IP 避免 IP 封禁。
- 图像识别:集成 OCR 技术自动识别验证码,降低人工干预。
- 候补购票:模拟 12306 官方候补逻辑,提升购票成功率。
六、总体代码展示(Al优化后)
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.chrome.options import Optionsimport timefrom datetime import datetimefrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECimport getpass# ----------------------# 浏览器反检测配置# ----------------------def create_chrome_options(): options = Options() # 隐藏自动化特征 options.add_experimental_option(\'excludeSwitches\', [\'enable-automation\']) options.add_experimental_option(\'useAutomationExtension\', False) options.add_argument(\'--disable-blink-features=AutomationsControlled\') # 伪装用户代理(可替换为真实浏览器UA) options.add_argument(\'user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36\') # 其他实用配置 options.add_argument(\'ignore-certificate-errors\') options.add_argument(\'--disable-gpu\') options.add_argument(\'--no-sandbox\') options.add_argument(\'--headless\') #无头模式 注释这句 可以展示出购票 过程 #不注释,大大缩短,购票时间 return options# ----------------------# 登录模块# ----------------------def login(driver): try: driver.get(\'https://kyfw.12306.cn/otn/resources/login.html\') wait = WebDriverWait(driver, 10) # 输入用户名和密码 user = input(\"请输入用户名: \") pwd = getpass.getpass(\"请输入密码: \") # 定位并输入用户名 username_input = wait.until(EC.presence_of_element_located((By.XPATH, \'//div/input[@id=\"J-userName\"]\'))) username_input.send_keys(user) # 定位并输入密码 password_input = wait.until(EC.presence_of_element_located((By.XPATH, \'//div/input[@id=\"J-password\"]\'))) password_input.send_keys(pwd) # 点击登录按钮 login_button = wait.until(EC.element_to_be_clickable((By.XPATH, \'//*[@id=\"J-login\"]\'))) login_button.click() # 二次验证:身份证后四位 code_id = input(\"请输入身份证后四位: \") id_input = wait.until(EC.presence_of_element_located((By.XPATH, \'/html/body/div[1]/div[4]/div[2]/div[1]/div/div[1]/input\'))) id_input.send_keys(code_id) # 点击获取短信验证码 get_code_button = wait.until(EC.element_to_be_clickable((By.XPATH, \'//*[@id=\"verification_code\"]\'))) get_code_button.click() time.sleep(2) # 输入短信验证码 code = input(\"请输入短信验证码: \") code_input = wait.until(EC.presence_of_element_located((By.XPATH, \'//*[@id=\"code\"]\'))) code_input.send_keys(code) # 检查登录结果 try: error_msg = wait.until(EC.visibility_of_element_located((By.XPATH, \'//*[@id=\"message\"]/p\'))).text if \"用户名或密码错误\" in error_msg: print(\"登录失败:用户名、密码或验证码错误\") return False except: print(\"登录成功!\") # 跳转到车票查询页面 ticket_link = wait.until(EC.element_to_be_clickable((By.XPATH, \'//*[@id=\"link_for_ticket\"]\'))) ticket_link.click() return True except Exception as e: print(f\"登录过程中出现错误:{e}\") return False# ----------------------# 车次查询模块# ----------------------def search_tickets(driver): try: wait = WebDriverWait(driver, 10) # 输入出发地和目的地 from_station = input(\"请输入出发地: \") to_station = input(\"请输入目的地: \") # 定位出发地输入框 from_input = wait.until(EC.presence_of_element_located((By.XPATH, \'//*[@id=\"fromStationText\"]\'))) from_input.clear() from_input.send_keys(from_station) # 定位目的地输入框 to_input = wait.until(EC.presence_of_element_located((By.XPATH, \'//*[@id=\"toStationText\"]\'))) to_input.clear() to_input.send_keys(to_station) # 处理出发日期 current_date = datetime.now().strftime(\"%Y-%m-%d\") user_date = input(\"输入出发日期(格式: YYYY-MM-DD,留空默认今日): \") departure_date = current_date if not user_date else user_date # 更新日期输入框 if departure_date != current_date: date_input = wait.until(EC.presence_of_element_located((By.XPATH, \'//*[@id=\"train_date\"]\'))) date_input.clear() date_input.send_keys(departure_date) # 点击查询按钮 search_button = wait.until(EC.element_to_be_clickable((By.XPATH, \'//*[@id=\"query_ticket\"]\'))) search_button.click() print(f\"正在查询{departure_date}从{from_station}到{to_station}的车票...\") time.sleep(3) # 等待查询结果加载 return departure_date except Exception as e: print(f\"查询车次时出现错误:{e}\") return None# ----------------------# 车票预订模块# ----------------------def book_ticket(driver, departure_date): try: wait = WebDriverWait(driver, 10) # 提取所有车次时间 time_list = [] train_elements = wait.until(EC.presence_of_all_elements_located((By.XPATH, \'//div[contains(@id, \"train_num_\")]\'))) for i, train in enumerate(train_elements): try: time_text = train.find_element(By.XPATH, \'./div[3]/strong[1]\').text time_list.append(time_text) except: continue if not time_list: print(\"未找到可用车次!\") return # 用户选择时间段 move_time = input(\"请选择出发时间段(1:06:00-12:00,2:12:00-18:00,3:18:00-24:00): \") time_ranges = { \'1\': (\'06:00--12:00\', 3), \'2\': (\'12:00--18:00\', 4), \'3\': (\'18:00--24:00\', 5) } if move_time not in time_ranges: print(\"无效选择!\") return # 选择时间段 range_name, option_index = time_ranges[move_time] time_option = wait.until(EC.element_to_be_clickable((By.XPATH, f\'//*[@id=\"cc_start_time\"]/option[{option_index}]\'))) time_option.click() print(f\"已筛选{range_name}的车次\") # 输入目标时间并匹配最接近车次 target_time = input(\"请输入目标时间(格式: HH:MM): \") closest_time = get_closest_time(target_time, time_list) print(f\"最接近的车次时间:{closest_time}\") # 等待预订按钮加载并点击 book_button = wait.until(EC.element_to_be_clickable((By.XPATH, f\'//a[@class=\"btn72\" and contains(text(), \"{closest_time}\")]\'))) book_button.click() time.sleep(2) # 选择乘客(默认第一个乘客,需根据实际情况调整) passenger = wait.until(EC.element_to_be_clickable((By.XPATH, \'//ul[@id=\"normal_passenger_id\"]/li[1]/input\'))) passenger.click() # 提交订单(需手动处理可能的验证码或确认弹窗) submit_button = wait.until(EC.element_to_be_clickable((By.XPATH, \'//*[@id=\"submitOrder_id\"]\'))) submit_button.click() print(\"已提交订单,请尽快完成支付!\") except Exception as e: print(f\"预订车票时出现错误:{e}\")# ----------------------# 时间匹配函数# ----------------------def get_closest_time(user_time, time_list): user_min = int(user_time[:2]) * 60 + int(user_time[3:]) time_diffs = [(abs(int(t[:2])*60 + int(t[3:]) - user_min), t) for t in time_list] return min(time_diffs, key=lambda x: x[0])[1]# ----------------------# 主程序入口# ----------------------if __name__ == \"__main__\": options = create_chrome_options() driver = webdriver.Chrome(options=options) if login(driver): departure_date = search_tickets(driver) if departure_date: book_ticket(driver, departure_date) input(\"按回车键退出程序...\") driver.quit()
作者原创
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.chrome.options import Options # 导入Options操作类import timefrom datetime import datetimefrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECimport getpass# 获取当前日期(格式:YYYY-MM-DD)current_date = datetime.now().strftime(\"%Y-%m-%d\")options = Options()options.add_argument(\'--headless\') #无头模式# 设置自动化特性扩展的关闭,防止被服务器检测到是由selenium驱动的options.add_experimental_option(\'excludeSwitches\', [\'enable-automation\'])# 设置关闭自动化特性,防止被服务器检测到是由selenium驱动的options.add_argument(\'--disable-blink-features=AutomationsControlled\')# 关闭证书报错options.add_argument(\'ignore-certificate-errors\')# 启动 WebDriver(假设你使用的是 Chrome) 如果这里不进行传参数 就是有界面模式driver = webdriver.Chrome(options = options)# driver = webdriver.Chrome()time.sleep(1)def Longin(): try: # 打开目标网页 driver.get(\'https://kyfw.12306.cn/otn/resources/login.html\') # 获取用户输入的账号和密码 user = input(\"请输入用户名: \") # pwd = input(\"请输入密码: \") pwd = getpass.getpass(\"请输入密码: \") # 输入时密码不会显示在屏幕上 # 使用 XPath 定位用户名输入框并输入 nameuser = driver.find_element(By.XPATH, \'//div/input[@id=\"J-userName\"]\') time.sleep(1) nameuser.send_keys(user) # 定位密码输入框并输入 password = driver.find_element(By.XPATH, \'//div/input[@id=\"J-password\"]\') time.sleep(1) password.send_keys(pwd) # 登录按钮点击 driver.find_element(By.XPATH, \'//*[@id=\"J-login\"]\').click() # 后续代码保持不变 code_id = input(\"请输入身份证后四位:\") id_cord = driver.find_element(By.XPATH, \'/html/body/div[1]/div[4]/div[2]/div[1]/div/div[1]/input\') id_cord.send_keys(code_id) print(\"验证码正在发送中,请耐心等待\") time.sleep(1) driver.find_element(By.XPATH, \'//*[@id=\"verification_code\"]\').click() time.sleep(1) id_code = driver.find_element(By.XPATH, \'//*[@id=\"code\"]\') code = input(\"请输入验证码:\") id_code.send_keys(f\"{code}\") try: error_element = driver.find_element(By.XPATH, \'//*[@id=\"message\"]/p\') if error_element.text == \"用户名或密码错误\": print(\"密码,用户名,验证码错误,请检查\") else: print(\"登录成功\") time.sleep(2) driver.find_element(By.XPATH, \'//*[@id=\"link_for_ticket\"]\').click() time.sleep(2) driver.find_element(By.XPATH, \'//*[@id=\"sureClick\"]\') Inquirer() except Exception as e: print(f\"未找到错误提示元素: {e}\") except Exception as e: print(\"程序运行发生错误\", e)def Inquirer(): try: chufadi = input(\"请输入出发地:\") # 获取出发地输入框 from_station_input = driver.find_element(By.XPATH, \'//*[@id=\"fromStationText\"]\') # 清空输入框 from_station_input.clear() # 输入出发地 from_station_input.send_keys(chufadi) mudidi = input(\"请输入目的地:\") end_station_input = driver.find_element(By.XPATH, \'//*[@id=\"toStationText\"]\') end_station_input.clear() end_station_input.send_keys(mudidi) from datetime import datetime, timedelta try: # 获取当前日期 current_date = datetime.now().strftime(\"%Y-%m-%d\") # 获取用户输入 user_input = input(\"不输入默认获取当日,回车跳过输入,输入出发时间格式(2025-5-20):\") # 处理用户输入 if not user_input.strip(): # 输入为空 departure_date = current_date print(f\"未输入日期,将查询今日({departure_date})车票\") else: try: # 验证并格式化日期 parsed_date = datetime.strptime(user_input, \"%Y-%m-%d\") departure_date = parsed_date.strftime(\"%Y-%m-%d\") except ValueError: print(\"警告:输入日期格式不正确,将使用默认日期\") departure_date = current_date # 如果不是查询当日,需要更新日期输入框 if departure_date != current_date: date_input = driver.find_element(By.XPATH, \'//*[@id=\"train_date\"]\') date_input.clear() date_input.send_keys(departure_date) # 点击查询按钮(合并重复逻辑) query_button = driver.find_element(By.XPATH, \'//*[@id=\"query_ticket\"]\') query_button.click() print(f\"正在查询{departure_date}的车票,请稍后...\") list_Train = [] for trin in range(0, 20): dizhi = driver.find_element(By.XPATH, f\'//*[@id=\"train_num_{trin}\"]/div/strong\') time.sleep(1) list_Train.append(dizhi.text) print(f\"\"\" 出发地 目的地 到达时间 {list_Train[trin]} {list_Train[trin+1]} {list_Train[trin+2]} \"\"\") except Exception as e: print(f\"程序运行发生错误,在输入日期 {e}\") except Exception as e: print(\"程序运行发生错误,在输入地点\", e)#下面这个会确定元素加载完才会进行下一步def Get_ticket(): time_list = [] chechi_number = driver.find_element(By.XPATH, \'//*[@id=\"trainum\"]\') chechi_number = int(chechi_number.text) for i in range(chechi_number): time_list.append(driver.find_element(By.XPATH, f\'//*[@id=\"train_num_{i}\"]/div[3]/strong[1]\').text) move_time = input(\"请输入出发时间段,\\n1: 06:00--12:00\\n2: 12:00--18:00\\n3: 18:00--24:00\") # 创建显式等待对象 wait = WebDriverWait(driver, 10) if move_time == \'1\': \"\"\" //*[@id=\"cc_start_time\"]/option[*] 选着时间段 #这个是通过固定时间选定这个预订标签 onclick 这个下面的时间 选着这个标签 //a[@class=\"btn72\" and contains(@onclick, \'21:02\')] \"\"\" driver.find_element(By.XPATH, \'//*[@id=\"cc_start_time\"]/option[3]\').click() accurate_time = input(\"输入准确时间,将会自动购买靠近该时间的车票(12:00)\") closest = get_closest_time(accurate_time, time_list) print(f\"最接近 {accurate_time} 的时间是: {closest}\") print(\'所有时间为\', str(time_list)) # 添加显式等待 wait.until( EC.visibility_of_element_located((By.XPATH, f\'//a[@class=\"btn72\" and contains(text(), \"{closest}\")]\'))) # 点击预定按钮 driver.find_element(By.XPATH, f\'//a[@class=\"btn72\" and contains(@onclick, \"{closest}\")]\').click() time.sleep(1) driver.find_element(By.XPATH, \'//*[@id=\"normalPassenger_0\"]\').click() # 点击坐车人按钮 driver.find_element(By.XPATH, \'//*[@id=\"dialog_xsertcj_cancel\"]\').click() # 点击取消按钮 driver.find_element(By.XPATH, \'//*[@id=\"submitOrder_id\"]\').click() # 点击提交订单按钮 if move_time == \'2\': driver.find_element(By.XPATH, \'//*[@id=\"cc_start_time\"]/option[4]\').click() accurate_time = input(\"输入准确时间,将会自动购买靠近该时间的车票(12:00)\") closest = get_closest_time(accurate_time, time_list) print(f\"最接近 {accurate_time} 的时间是: {closest}\") print(\'所有时间为\', str(time_list)) # 添加显式等待 wait.until( EC.visibility_of_element_located((By.XPATH, f\'//a[@class=\"btn72\" and contains(text(), \"{closest}\")]\'))) # 点击预定按钮 driver.find_element(By.XPATH, f\'//a[@class=\"btn72\" and contains(@onclick, \"{closest}\")]\').click() time.sleep(1) driver.find_element(By.XPATH, \'//*[@id=\"normalPassenger_0\"]\').click() # 点击坐车人按钮 driver.find_element(By.XPATH, \'//*[@id=\"dialog_xsertcj_cancel\"]\').click() # 点击取消按钮 driver.find_element(By.XPATH, \'//*[@id=\"submitOrder_id\"]\').click() # 点击提交订单按钮 if move_time == \'3\': driver.find_element(By.XPATH, \'//*[@id=\"cc_start_time\"]/option[5]\').click() accurate_time = input(\"输入准确时间,将会自动购买靠近该时间的车票(12:00)\") closest = get_closest_time(accurate_time, time_list) print(f\"最接近 {accurate_time} 的时间是: {closest}\") print(\'所有时间为\', str(time_list)) # 添加显式等待 wait.until( EC.visibility_of_element_located((By.XPATH, f\'//a[@class=\"btn72\" and contains(text(), \"{closest}\")]\'))) # 点击预定按钮 driver.find_element(By.XPATH, f\'//a[@class=\"btn72\" and contains(@onclick, \"{closest}\")]\').click() time.sleep(1) driver.find_element(By.XPATH, \'//*[@id=\"normalPassenger_0\"]\').click() # 点击坐车人按钮 driver.find_element(By.XPATH, \'//*[@id=\"dialog_xsertcj_cancel\"]\').click() # 点击取消按钮 driver.find_element(By.XPATH, \'//*[@id=\"submitOrder_id\"]\').click() # 点击提交订单按钮def get_closest_time(user_time, time_list): user_minutes = int(user_time[:2]) * 60 + int(user_time[3:]) time_diffs = [(abs(int(t[:2]) * 60 + int(t[3:]) - user_minutes), t) for t in time_list] return min(time_diffs)[1]if __name__ == \'__main__\': Longin()# 等待一段时间以观察结果# time.sleep()input(\"回车结束\")# 关闭浏览器driver.quit()