import datetime
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
import time
options = Options()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
wd = webdriver.Chrome()
wd.minimize_window()
wd.implicitly_wait(5)
wait = WebDriverWait(wd, 5)
chrome_options = Options()
chrome_options.page_load_strategy = "eager"
driver = webdriver.Chrome(options=chrome_options)
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import time
options = Options()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
wd = webdriver.Chrome()
wd.minimize_window()
wait = WebDriverWait(wd, 5)
actions = ActionChains(wd)
wd.implicitly_wait(5)
def input_with_enter(element, text):
"""带回车确认的输入方法"""
element.clear()
time.sleep(0.3)
for char in text:
element.send_keys(char)
time.sleep(0.1)
element.send_keys(Keys.ENTER)
time.sleep(0.5)
def set_station_auto(field_id, prompt):
"""自动化设置车站输入(带自动回车确认)"""
while True:
try:
input_field = wait.until(EC.element_to_be_clickable((By.ID, field_id)))
input_field.click()
wd.execute_script(f"document.getElementById('{field_id}').value='';")
time.sleep(0.5)
city_name = input(prompt)
if not city_name:
continue
input_with_enter(input_field, city_name)
if input_field.get_attribute("value"):
print(f"✅ 已设置: {input_field.get_attribute('value')}")
return True
except Exception as e:
print(f"❌ 设置失败: {str(e)}")
wd.save_screenshot(f"error_{field_id}.png")
def switch_to_new_window():
"""切换到新打开的窗口"""
original_window = wd.current_window_handle
WebDriverWait(wd, 10).until(lambda d: len(d.window_handles) > 1)
for window_handle in wd.window_handles:
if window_handle != original_window:
wd.switch_to.window(window_handle)
break
print(f"已切换到新窗口,当前URL: {wd.current_url}")
return True
def print_ticket_info():
"""打印车票信息"""
print("\n=== 可购车次信息 ===")
try:
wait.until(EC.presence_of_element_located((By.ID, "t-list")))
train_list = wait.until(EC.presence_of_all_elements_located(
(By.CSS_SELECTOR, "#queryLeftTable tr[id^='ticket_']")))
trains = []
for i, train in enumerate(train_list, 1):
try:
number = train.find_element(By.CLASS_NAME, "number").text
start_time = train.find_element(By.CLASS_NAME, "start-t").text
arrive_time = train.find_element(By.CLASS_NAME, "color999").text
duration = train.find_element(By.CLASS_NAME, "ls").text
seat_types = train.find_elements(By.CSS_SELECTOR, ".seat[class^='seat_']")
seat_info = []
for seat in seat_types:
seat_name = seat.get_attribute("textContent").strip()
seat_count = seat.find_element(By.CLASS_NAME, "seat_surplus").text
seat_info.append(f"{seat_name}:{seat_count}")
train_info = {
"index": i,
"number": number,
"departure": start_time,
"arrival": arrive_time,
"duration": duration,
"seats": " | ".join(seat_info)
}
trains.append(train_info)
print(
f"{i}. 车次: {number} | 出发: {start_time} | 到达: {arrive_time} | 历时: {duration} | 余票: {' | '.join(seat_info)}")
except Exception as e:
print(f"解析车次信息时出错: {str(e)}")
continue
return trains
except Exception as e:
print(f"获取车票信息失败: {str(e)}")
wd.save_screenshot("ticket_info_error.png")
return None
def select_and_book(train_list):
"""选择车次并购票"""
while True:
choice = input("\n请输入要购买的车次编号(1-{}), 或输入q退出: ".format(len(train_list)))
if choice.lower() == 'q':
return False
try:
index = int(choice) - 1
if 0 <= index < len(train_list):
selected_train = train_list[index]
print(f"\n您选择了: {selected_train['number']}")
original_window = wd.current_window_handle
book_btn = WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.XPATH, "//*[@id='ticket_5500000G1401_01_05']/td[13]/a")))
book_btn.click()
print("正在跳转到预订页面...")
try:
switch_to_new_window()
except:
wait.until(EC.url_changes(wd.current_url))
print(f"页面已跳转,当前URL: {wd.current_url}")
return True
else:
print("请输入有效的编号!")
except ValueError:
print("请输入数字!")
def handle_passenger_selection():
"""处理乘客选择"""
try:
orders = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='ticket_5l00000G1006_01_04']/td[13]/a")))
orders.click()
checkbox = wait.until(EC.element_to_be_clickable((By.ID, "normalPassenger_0")))
checkbox.click()
cancel_btn = wait.until(EC.element_to_be_clickable((By.ID, "dialog_xsertcj_cancel")))
cancel_btn.click()
submit_orders = wait.until(EC.element_to_be_clickable((By.ID, "submitOrder_id")))
submit_orders.click()
ok_btn = wait.until(EC.element_to_be_clickable((By.ID, "qr_submit_id")))
ok_btn.click()
return True
except Exception as e:
print(f"购票过程中出错: {str(e)}")
wd.save_screenshot("book_error.png")
return False
try:
wd.get("https://kyfw.12306.cn/otn/resources/login.html")
print("已打开登录页面")
account_login = WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.XPATH, "//*[@id='toolbar_Div']/div[2]/div[2]/ul/li[1]/a")))
account_login.click()
print("已切换到账号登录")
username_input = WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.ID, "J-userName")))
username_input.clear()
username_input.send_keys("15030593992")
print("已输入用户名")
password_input = WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.ID, "J-password")))
password_input.clear()
password_input.send_keys("15030593992zzw")
print("已输入密码")
login_btn = WebDriverWait(wd, 10).until(
EC.element_to_be_clickable((By.ID, "J-login")))
login_btn.click()
print("已点击登录按钮")
variy_input = WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.XPATH, "//*[@id='id_card']")))
variy_input.clear()
variy_input.send_keys("2510")
print("已输入身份证")
get_code = WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.XPATH, "//*[@id='verification_code']")))
get_code.click()
code_input = WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.XPATH, " // *[ @ id = 'code']")))
code = input("请手动输入:")
code_input.send_keys(code)
print("已输入身份证后四位")
btn = WebDriverWait(wd, 10).until(
EC.presence_of_element_located((By.XPATH, " // *[ @ id = 'sureClick']")))
btn.click()
time.sleep(5)
wd.get("https://www.12306.cn/index/index.html")
print("✅ 已打开12306首页")
set_station_auto("fromStationText", "请输入出发地(如'北京')然后按回车: ")
set_station_auto("toStationText", "请输入目的地(如'上海')然后按回车: ")
date_input = wait.until(EC.element_to_be_clickable((By.ID, "train_date")))
travel_date = input("请输入日期(YYYY-MM-DD)然后按回车: ")
input_with_enter(date_input, travel_date)
print(f"📅 已设置日期: {date_input.get_attribute('value')}")
search_btn = wait.until(EC.element_to_be_clickable((By.ID, "search_one")))
search_btn.click()
print("🔍 正在查询车票...")
try:
switch_to_new_window()
except:
print("没有新窗口,继续在当前窗口操作")
train_list = print_ticket_info()
if train_list and select_and_book(train_list):
handle_passenger_selection()
except Exception as e:
print(f"❗ 发生错误: {str(e)}")
wd.save_screenshot("main_error.png")
finally:
input("按回车键退出...")
wd.quit()