跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python算法

Python 基于 Selenium 实现 12306 自动购票脚本

介绍使用 Python 的 Selenium 自动化库模拟浏览器操作,实现 12306 铁路售票系统的自动查询与下单流程。内容涵盖环境配置、核心类设计、关键 XPath 定位及等待机制处理。代码示例展示了从登录验证到订单提交的完整逻辑,旨在提供技术参考与学习思路。请注意,此类脚本仅供技术研究,实际使用需遵守平台规则。

鲜活发布于 2025/2/6更新于 2026/10/23108 浏览
Python 基于 Selenium 实现 12306 自动购票脚本

Python 基于 Selenium 实现 12306 自动购票脚本

前言

本教程演示如何利用 Python 的 Selenium 自动化测试模块模拟人类操作浏览器,从而实现对 12306 网站的车票查询与预订功能。通过编写脚本,可以自动化完成登录、查票、选座及提交订单等步骤。

环境准备

在运行脚本前,请确保已完成以下准备工作:

  1. Python 环境:安装 Python 3.x 版本。
  2. 依赖库:使用 pip 安装 Selenium 库。
    pip install selenium
    
  3. 浏览器驱动:下载与本地 Chrome 浏览器版本一致的 chromedriver.exe。将驱动文件放置于脚本同一目录下,或将其添加到系统环境变量 PATH 中。
  4. 浏览器设置:建议使用 Chrome 浏览器,并关闭自动更新弹窗干扰。

核心代码实现

以下是完整的抢票脚本结构,包含初始化、登录、搜索、下单等核心方法。

import time
import datetime
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class Qiangpiao():
    def __init__(self, from_station, to_station, depart_time, train_num, passenger):
        self.login_url = 'https://kyfw.12306.cn/otn/resources/login.html'
        self.init_my_url = 'https://kyfw.12306.cn/otn/view/index.html'
        self.order_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
        
        self.from_station = from_station
        .to_station = to_station
        .depart_time = depart_time
        .train_num = train_num
        .passenger = passenger
        
        .now_month = datetime.date.today().month
        .leave_month = (.depart_time.split()[])
        .leave_day = (.depart_time.split()[])
        
        .driver = webdriver.Chrome()

     ():
        .driver.get(.login_url)
        .driver.set_window_size(, )
        
        WebDriverWait(.driver, ).until(EC.url_to_be(.init_my_url))
        ()

     ():
        time.sleep()
        :
            .driver.find_element(By.XPATH, ).click()
         Exception:
            

     ():
        action = ActionChains(.driver)
        element = .driver.find_element(By.LINK_TEXT, )
        action.move_to_element(element).perform()
        .driver.find_element(By.XPATH, ).click()
        .driver.find_element(By.LINK_TEXT, ).click()

     ():
        
        .driver.find_element(By.ID, ).click()
        .driver.find_element(By.ID, ).send_keys(.from_station)
        .driver.find_element(By.ID, ).send_keys(Keys.ENTER)
        
        
        .driver.find_element(By.ID, ).click()
        .driver.find_element(By.ID, ).send_keys(.to_station)
        .driver.find_element(By.ID, ).send_keys(Keys.ENTER)
        
        
        .driver.find_element(By.ID, ).click()
         .leave_month == .now_month:
            xpath_str = 
         .leave_month == .now_month + :
            xpath_str = 
        :
            ()
            

         EC.element_to_be_clickable((By.XPATH, xpath_str)):
            .driver.find_element(By.XPATH, xpath_str).click()
        :
            ()
            

        
        WebDriverWait(.driver, ).until(EC.element_to_be_clickable((By.ID, )))
        search_btn = .driver.find_element(By.ID, )
        search_btn.click()
        
        
        WebDriverWait(.driver, ).until(EC.presence_of_element_located((By.XPATH, )))

     ():
        train_num_list = []
        train_num_ele_list = .driver.find_elements(By.XPATH, )
         t  train_num_ele_list:
            train_num_list.append(t.text)
        
        tr_list = .driver.find_elements(By.XPATH, )
        
         .train_num  train_num_list:
             tr  tr_list:
                train_num = tr.find_element(By.XPATH, ).text
                 .train_num == train_num:
                    text_1 = tr.find_element(By.XPATH, ).text
                    text_2 = tr.find_element(By.XPATH, ).text
                    
                     (text_1 ==   text_1.isdigit())  (text_2 ==   text_2.isdigit()):
                        order_btn = tr.find_element(By.CLASS_NAME, )
                        order_btn.click()
                        
                        WebDriverWait(.driver, ).until(EC.url_to_be(.order_url))
                        
                        
                        .driver.find_element(By.XPATH, ).click()
                        
                        
                         EC.presence_of_element_located((By.XPATH, )):
                            .driver.find_element(By.ID, ).click()
                        
                        
                        .driver.find_element(By.ID, ).click()
                        time.sleep()
                        
                        
                        .driver.find_element(By.ID, ).click()
                        ()
                        
                    :
                        ()
        :
            ()

     ():
        ._login()
        ._pop_window()
        ._enter_order_ticket()
        ._search_ticket()
        ._order_ticket()
        time.sleep()
        .driver.quit()

 __name__ == :
    
    qiangpiao = Qiangpiao(, , , , )
    qiangpiao.run()
self
self
self
self
self
self
int
self
'-'
0
self
int
self
'-'
1
self
def
_login
self
self
self
self
1300
800
# 显式等待登录成功
self
1000
self
print
'登录成功!'
def
_pop_window
self
1
try
self
'//*[@class="dzp-confirm"]/div[2]/div[3]/a'
except
pass
def
_enter_order_ticket
self
self
self
'车票'
self
'//*[@id="J-chepiao"]/div/div[1]/ul/li[1]/a'
self
'确认'
def
_search_ticket
self
# 出发地输入
self
"fromStationText"
self
"fromStationText"
self
self
"fromStationText"
# 目的地输入
self
"toStationText"
self
"toStationText"
self
self
"toStationText"
# 出发日期选择
self
"train_date"
if
self
self
f"//div[@class='cal-wrap']/div[1]/div[2]/div[{self.leave_day}]"
elif
self
self
1
f"//div[@class='cal-wrap']/div[2]/div[2]/div[{self.leave_day}]"
else
print
"月份超前一个月以上,无法购票!"
return
if
self
else
print
"当前日期未到或已过售票日期,无法购票!"
return
# 点击查询按钮
self
1000
"query_ticket"
self
"query_ticket"
# 等待结果加载
self
1000
'//*[@id="queryLeftTable"]/tr'
def
_order_ticket
self
self
'//tr/td[1]/div/div[1]/div/a'
for
in
self
'//*[@id="queryLeftTable"]/tr[not(@datatran)]'
if
self
in
for
in
"./td[1]/div/div[1]/div/a"
if
self
"./td[4]"
"./td[8]"
if
"有"
or
or
"有"
or
"btn72"
self
1000
self
# 选定乘车人
self
f'//*[@id="normal_passenger_id"]/li/label[contains(text(),"{self.passenger}")]'
# 学生票提示处理
if
'//div[@id="dialog_xsertcj"]'
self
'dialog_xsertcj_ok'
# 提交订单
self
'submitOrder_id'
2
# 确认订单
self
'qr_submit_id'
print
"购票成功!"
break
else
print
"二等座无票!"
else
print
"无此列车!"
def
run
self
self
self
self
self
self
6
self
if
'__main__'
# 注意:此处仅为示例参数,请根据实际情况修改
"昆明"
"武汉"
"1-27"
"G1540"
"张三"

关键技术点解析

  1. WebDriver 初始化:使用 webdriver.Chrome() 启动浏览器实例。
  2. 显式等待:利用 WebDriverWait 和 expected_conditions 确保元素加载完成后再操作,避免页面未渲染导致的错误。
  3. XPath 定位:通过动态生成的 XPath 字符串定位日历中的具体日期,适应不同月份的布局变化。
  4. 动作链:使用 ActionChains 模拟鼠标悬停操作,触发下拉菜单显示。
  5. 异常处理:在弹窗关闭等步骤中加入 try-except 块,防止因界面差异导致脚本报错中断。

注意事项

  1. 合规性:本脚本仅用于 Python 自动化技术学习与研究。请勿用于恶意刷票或违反 12306 服务条款的行为,否则可能导致账号被封禁。
  2. 验证码:12306 登录环节通常包含图形验证码,脚本中采用手动扫码或输入方式,自动化绕过验证码可能涉及安全风险。
  3. 版本兼容性:Chrome 浏览器升级后,chromedriver 需同步更新,否则会导致连接失败。
  4. 网络延迟:抢票对网络延迟敏感,建议在网络稳定环境下运行,并根据实际情况调整 time.sleep 的时间间隔。

目录

  1. Python 基于 Selenium 实现 12306 自动购票脚本
  2. 前言
  3. 环境准备
  4. 核心代码实现
  5. 关键技术点解析
  6. 注意事项

更多推荐文章

查看全部
  • Python 结合 Hadoop 实现用户网站浏览数据分析
  • 基于 Django 与 Python 的电商用户行为分析系统设计与实现
  • Windows 10/11 部署 OpenClaw 机器人控制框架指南
  • 亮数据爬虫 API 深度评测:高并发采集与反爬绕过方案
  • FPGA 实现 UART 串口通信详解
  • 纯前端 JavaScript 通过 IP 地址获取用户地理位置
  • 小米智能家居接入 Home Assistant 配置指南
  • iOS 网络安全实战:HTTPS 通信与证书锁定防抓包
  • Python 接口、抽象基类与协议详解
  • Redis Cluster 哈希槽分片机制与 Linux 集群搭建实操
  • 近端策略优化算法 (PPO) 详解与代码实现
  • 文心一言 4.5:中文能力实测与本地部署记录
  • Git 版本控制核心原理与常用操作指南
  • LLM 高效微调方法详解:Adapter、LoRA、Prompt 等六大主流方案对比
  • LLM 结构化数据生成原理详解:基于 lm-format-enforcer
  • 人工智能改造传统医疗设备的现实路径
  • 基于 Qwen3-VL 与 LLaMA-Factory 的 Grounding 任务 LoRA 微调实战
  • 零基础入门网络安全:2023 年专业学习路线指南
  • Trae AI 将设计稿自动生成前端代码图文指南
  • Go Web 开发核心理论与实战基础

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online