⚠️ 法律与道德声明
本工具仅供个人学习和研究使用,严禁用于商业目的或扰乱正常购票秩序。
使用本工具产生的一切后果由使用者自行承担。
请遵守 12306 官方使用条款,合理购票。
基于 Python + Selenium 的 12306 火车票自动抢票工具,全程通过 Selenium 模拟真实用户操作,不依赖反向工程 API 参数,稳定可靠。
- 扫码登录:手机 12306 APP 扫码,规避账号密码登录的风控拦截
- Cookies 持久化:自动保存/加载登录凭证,有效期内的下次运行无需重新扫码
- 智能查询:通过浏览器内 XHR 复用登录会话,按车次 + 时间范围筛选余票
- 一键下单:点击预订按钮 → 勾选乘车人 → 选择座席(A/B/C/D/F) → 提交订单 → 确认弹窗 → 跳转支付页
- 消息通知:支持邮件 / Server 酱推送抢票结果
- 反爬策略:UA 轮换、随机延迟、隐藏 webdriver 特征
12306_creep/
├── main.py # 主程序入口(登录→查询→下单 完整循环)
├── config.py # 配置管理模块
├── config.json # 配置文件(用户填写)
├── requirements.txt # 依赖列表
├── station_codes.py # 站点电报码映射(自动拉取 + 缓存)
├── auth/ # 登录认证模块
│ ├── __init__.py
│ └── login.py # 扫码登录 + Cookies 持久化
├── query/ # 车票查询模块
│ ├── __init__.py
│ └── ticket_query.py # 余票查询与解析(浏览器内 XHR)
├── order/ # 订单提交模块
│ ├── __init__.py
│ └── submit_order.py # 纯 Selenium 下单(点击按钮 + 选座 + 确认弹窗)
├── utils/ # 工具模块
│ ├── __init__.py
│ ├── logger.py # 日志系统(loguru 控制台 + 文件)
│ ├── exceptions.py # 异常定义与自动重试装饰器
│ ├── notification.py # 邮件 / Server 酱通知
│ └── helpers.py # 随机延迟、UA 轮换、信息格式化
└── logs/ # 日志输出目录(自动生成)
pip install -r requirements.txt确保系统已安装 Google Chrome 浏览器。
Selenium 4.x 的 Selenium Manager 会自动下载对应版本的 ChromeDriver,无需手动配置。
将 config.example.json 复制为 config.json 并编辑填写个人信息。以下为完整配置项说明:
| 配置项 | 说明 | 示例 |
|---|---|---|
from_station |
出发站中文名 | "上海" |
to_station |
到达站中文名 | "成都" |
train_date |
出发日期 | "2026-07-21" |
target_trains |
目标车次列表 | ["G237", "G1974"] |
time_range |
出发时间范围 | "07:00-20:00" |
| 配置项 | 说明 | 示例 |
|---|---|---|
name |
乘车人姓名(需与12306账号一致) | "张三" |
id_card |
身份证号 | "110101199001011234" |
phone |
手机号 | "13800138000" |
seat_type |
座位类型 | "二等座" / "一等座" / "商务座" |
seat_preference |
座席偏好(可选) | "A" / "B" / "C" / "D" / "F",不填则跳过 |
座席偏好说明:高铁二等座 A/F 为靠窗,C/D 为过道,B 为中间。程序会依次尝试
<select>下拉框、radio 按钮、JavaScript 三种方式选择座席。
| 配置项 | 说明 | 默认值 |
|---|---|---|
query_interval |
查询间隔(秒) | 5 |
max_retry |
最大查询轮次 | 100 |
request_timeout |
请求超时(秒) | 30 |
random_delay_range |
随机延迟范围(秒) | [1, 3] |
| 配置项 | 说明 | 默认值 |
|---|---|---|
headless |
无头模式(扫码登录建议关闭) | false |
window_size |
窗口尺寸 | "1920,1080" |
- 邮件通知:填写
email_smtp、email_user、email_pass(授权码)、email_to,并将enable_email设为true - Server 酱:填写
serverchan_key,并将enable_serverchan设为true,可推送到微信
python main.py如需指定自定义配置文件:
python main.py my_config.json┌─────────────┐
│ 1. 启动浏览器 │
└──────┬──────┘
↓
┌─────────────┐ 有 Cookies 且有效
│ 2. 登录认证 │──────────────────────┐
│ (扫码/Cookies)│ │
└──────┬──────┘ │
↓ 无/失效 │
┌─────────────┐ │
│ 手机APP扫码 │ │
│ 保存Cookies │ │
└──────┬──────┘ │
└─────────────┬──────────────┘
↓
┌─────────────────────┐
│ 3. 循环查询余票 │ ← 按配置间隔循环
│ leftTicket 页面 │
│ 浏览器内 XHR 请求 │
└────────┬────────────┘
↓ 发现余票
┌─────────────────────┐
│ 4. 自动下单 │
│ a. 点击「预订」按钮 │
│ b. 勾选乘车人 │
│ c. 选择座席偏好 │
│ d. 点击「提交订单」 │
│ e. 确认弹窗 │
│ f. 跳转支付页 │
└────────┬────────────┘
↓
┌─────────────────────┐
│ 5. 手动完成支付 │ ← 程序不自动支付
└─────────────────────┘
- 程序启动后自动打开 Chrome 浏览器
- 优先尝试加载已保存的 Cookies 登录;若无效则自动展示二维码
- 使用手机 12306 APP 扫码登录(程序等待最多 180 秒)
- 登录成功自动保存 Cookies,下次启动可直接跳过扫码
- 开始循环查询余票(按配置的间隔 + 随机延迟)
- 发现满足条件的余票后自动进入下单流程
- 支付环节保留人工确认,程序不会自动支付
- 首次运行需扫码登录,之后 Cookies 会缓存到
cookies.json - 若 Cookies 未过期,下次运行直接注入使用,无需重复扫码
- 建议乘车人已在 12306 账号中提前添加为常用联系人
- 程序异常退出后浏览器会保留 60 秒,方便人工接管页面
整个下单流程通过 Selenium 操作页面按钮完成,无需手动构造 API 请求参数:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 填写出发站、到达站、日期 | 通过 fromStationText / toStationText 输入框 |
| 2 | 点击「查询」按钮 | 等待结果表格加载 |
| 3 | 点击目标车次的「预订」按钮 | 通过 XPath 定位车次行 |
| 4 | 等待确认页加载 | 检测 normal_passenger_id 元素 |
| 5 | 勾选乘车人 | 按姓名匹配 checkbox |
| 6 | 选择座席偏好 | 支持 A/B/C/D/F 五种座席 |
| 7 | 点击「提交订单」 | #submitOrder_id 按钮 |
| 8 | 确认弹窗 | 自动点击确认按钮 |
| 9 | 等待跳转支付页 | 轮询检测 URL 变化 |
- UA 轮换:每次启动随机选择 User-Agent
- 随机延迟:所有操作间加入随机延迟(1-3 秒)
- 隐藏自动化特征:移除
navigator.webdriver标识,禁用AutomationControlled - 浏览器内 XHR:查询请求通过浏览器
fetch发起,复用 Cookies 与风控上下文 - 纯 Selenium 下单:不再通过
requests库发送 API 请求,完全模拟真实用户点击 - 合理查询间隔:默认 5 秒 + 随机抖动,避免高频请求
- 控制台实时输出彩色日志
logs/ticket_YYYY-MM-DD.log:全量日志logs/error_YYYY-MM-DD.log:仅错误日志
A: 确保已安装 Chrome 浏览器。Selenium 4.x 的 Selenium Manager 会自动下载对应驱动。
A: 默认等待 180 秒,可在 auth/login.py 中调整 timeout 参数。确保手机 12306 APP 已登录。
A: 程序自动从 12306 拉取全量站点映射并缓存到 station_codes.json。若网络异常,删除该文件后重新运行即可重新拉取。
A: 可能原因:12306 高并发限流、登录过期、乘车人信息未在 12306 添加。建议检查 cookies 是否过期,重新扫码登录后再试。
A: 12306 座席选择 UI 因车次而异,程序会依次尝试 <select> 下拉框、radio 按钮、JavaScript 三种方式。如都不生效,请检查 seat_preference 是否填写了有效值(A/B/C/D/F)。
本工具仅供学习交流使用,不保证抢票成功率,不对使用后果承担责任。请遵守相关法律法规和 12306 用户协议,理性购票。