Skip to content

Repository files navigation

12306 自动抢票系统

⚠️ 法律与道德声明
本工具仅供个人学习和研究使用,严禁用于商业目的或扰乱正常购票秩序。
使用本工具产生的一切后果由使用者自行承担。
请遵守 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/                   # 日志输出目录(自动生成)

环境准备

1. 安装 Python 依赖

pip install -r requirements.txt

2. 安装 Chrome 浏览器

确保系统已安装 Google Chrome 浏览器。

Selenium 4.x 的 Selenium Manager 会自动下载对应版本的 ChromeDriver,无需手动配置。

配置说明

config.example.json 复制为 config.json 并编辑填写个人信息。以下为完整配置项说明:

行程配置 (trip)

配置项 说明 示例
from_station 出发站中文名 "上海"
to_station 到达站中文名 "成都"
train_date 出发日期 "2026-07-21"
target_trains 目标车次列表 ["G237", "G1974"]
time_range 出发时间范围 "07:00-20:00"

乘客配置 (passengers)

配置项 说明 示例
name 乘车人姓名(需与12306账号一致) "张三"
id_card 身份证号 "110101199001011234"
phone 手机号 "13800138000"
seat_type 座位类型 "二等座" / "一等座" / "商务座"
seat_preference 座席偏好(可选) "A" / "B" / "C" / "D" / "F",不填则跳过

座席偏好说明:高铁二等座 A/F 为靠窗,C/D 为过道,B 为中间。程序会依次尝试 <select> 下拉框、radio 按钮、JavaScript 三种方式选择座席。

抢票策略 (strategy)

配置项 说明 默认值
query_interval 查询间隔(秒) 5
max_retry 最大查询轮次 100
request_timeout 请求超时(秒) 30
random_delay_range 随机延迟范围(秒) [1, 3]

浏览器配置 (browser)

配置项 说明 默认值
headless 无头模式(扫码登录建议关闭) false
window_size 窗口尺寸 "1920,1080"

通知配置(可选)

  • 邮件通知:填写 email_smtpemail_useremail_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. 手动完成支付       │ ← 程序不自动支付
└─────────────────────┘
  1. 程序启动后自动打开 Chrome 浏览器
  2. 优先尝试加载已保存的 Cookies 登录;若无效则自动展示二维码
  3. 使用手机 12306 APP 扫码登录(程序等待最多 180 秒)
  4. 登录成功自动保存 Cookies,下次启动可直接跳过扫码
  5. 开始循环查询余票(按配置的间隔 + 随机延迟)
  6. 发现满足条件的余票后自动进入下单流程
  7. 支付环节保留人工确认,程序不会自动支付

使用提示

  • 首次运行需扫码登录,之后 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:仅错误日志

常见问题

Q: Chrome 驱动启动失败?

A: 确保已安装 Chrome 浏览器。Selenium 4.x 的 Selenium Manager 会自动下载对应驱动。

Q: 扫码登录超时?

A: 默认等待 180 秒,可在 auth/login.py 中调整 timeout 参数。确保手机 12306 APP 已登录。

Q: 查询不到站点?提示"未找到站点电报码"?

A: 程序自动从 12306 拉取全量站点映射并缓存到 station_codes.json。若网络异常,删除该文件后重新运行即可重新拉取。

Q: 订单提交后提示"系统繁忙"?

A: 可能原因:12306 高并发限流、登录过期、乘车人信息未在 12306 添加。建议检查 cookies 是否过期,重新扫码登录后再试。

Q: 座席选择不生效?

A: 12306 座席选择 UI 因车次而异,程序会依次尝试 <select> 下拉框、radio 按钮、JavaScript 三种方式。如都不生效,请检查 seat_preference 是否填写了有效值(A/B/C/D/F)。

免责声明

本工具仅供学习交流使用,不保证抢票成功率,不对使用后果承担责任。请遵守相关法律法规和 12306 用户协议,理性购票。

About

A program that helps grab tickets on 12306

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages