12306 查询与订票辅助技能,支持余票查询、经停站查询、中转换乘、候补查询与提交/取消、登录状态检查、密码登录与二维码登录、下单与支付链接获取;当用户提到火车票、高铁票、经停站、中转、候补或 12306 查票时触发。
Scanned 9/8/2026
Install to Claude Code
npx -y skills add infometa/workbuddyskills --skill 12306-train-assistant --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of 12306 Train Assistant?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/infometa-12306-train-assistant-workbuddyskills)More formats (shields.io, HTML) on the badges page.
---
name: 12306-train-assistant
description: 12306 查询与订票辅助技能,支持余票查询、经停站查询、中转换乘、候补查询与提交/取消、登录状态检查、密码登录与二维码登录、下单与支付链接获取;当用户提到火车票、高铁票、经停站、中转、候补或 12306 查票时触发。
description_zh: "12306 全功能辅助:余票/中转/候补/下单/支付,需登录账号"
description_en: "Full 12306 assistant: ticket query, transfer, waitlist, booking and payment"
version: 0.1.7
allowed-tools: Bash,Read
---
# 12306 CLI Skill 🚄
## 目标
用本仓库的 `client.py` 完成 12306 相关查询与下单辅助,优先覆盖:
- 余票查询:`left-ticket`
- 中转换乘:`transfer-ticket`
- 中转下单:`transfer-book`
- 经停站:`route`(支持 `--train-code` 自动解析)
- 登录态检查:`status`
- 二维码登录:`qr-login-create`
- 候补管理:`candidate-queue` / `candidate-orders` / `candidate-submit` / `candidate-cancel` / `candidate-pay`
- 支付信息:`order-pay`
- 需要登录的操作:`passengers` / `orders` / `order-no-complete` / `book` / `transfer-book` / `order-pay` / `candidate-submit` / `candidate-cancel` / `candidate-pay`
## 触发信号
用户提到下列需求时触发本技能:
- “查明天北京到上海余票”
- “G1033 经停站”
- “深圳到拉萨怎么中转”
- “把第1个中转方案下单”
- “候补排队状态怎么样”
- “12306 登录状态”
## 执行原则
1. 默认用 `text` 输出(便于用户阅读);仅在用户明确要求结构化数据时加 `--json`。
2. 解析相对日期(今天/明天/后天)为 `YYYY-MM-DD` 后再执行命令。
3. 站名支持中文/拼音/三字码,直接传给命令即可。
4. `route` 优先用 `--train-code`,减少用户提供 `train_no` 的负担。
5. 失败时先给出可执行修复建议(缺参数、日期格式、站名不匹配、风控限制等)。
6. `book`/`transfer-book` 成功后优先告知订单号,并提示下一步执行 `order-pay` 获取支付参数;若网页支付不可用,建议去 12306 App 的“待支付订单”继续支付。
7. `qr-login-create` 会自动后台启动登录检查;扫码确认后统一用 `status` 判断是否已登录。
## 常用示例
### 示例 1:余票查询
```bash
python3 client.py left-ticket --date 2026-03-23 --from 北京南 --to 上海虹桥
python3 client.py left-ticket --date 2026-03-23 --from 北京 --to 上海 --limit 10 --json
```
### 示例 2:中转换乘
```bash
python3 client.py transfer-ticket --date 2026-03-23 --from 深圳 --to 拉萨 --limit 10
python3 client.py transfer-ticket --date 2026-03-23 --from 深圳 --to 拉萨 --middle 西安 --json
```
### 示例 2.1:中转下单
```bash
# 先预检(不最终提交)
python3 client.py transfer-book --date 2026-03-23 --from 成都 --to 广安 --plan-index 1 --seat second_class --passengers 张三 --dry-run
# 正式提交
python3 client.py transfer-book --date 2026-03-23 --from 成都 --to 广安 --plan-index 1 --seat second_class --passengers 张三
```
### 示例 3:经停站
```bash
# 推荐:直接用车次号,脚本自动解析 train_no
python3 client.py route --train-code C956 --date 2026-03-23 --from 南部 --to 南充北
# 已知 train_no 时可直查
python3 client.py route --train-no 760000C95604 --date 2026-03-23 --from NBE --to NCE
```
### 示例 4:登录与状态
```bash
python3 client.py status
python3 client.py login --username <账号> --password <密码>
python3 client.py login --username <账号> --id-last4 <证件后4位> --send-sms
python3 client.py login --username <账号> --id-last4 <证件后4位> --sms-code <6位验证码>
# 二维码登录流程
python3 client.py qr-login-create
python3 client.py status
```
### 示例 5:乘车人与订单
```bash
python3 client.py passengers --limit 50
python3 client.py orders --where G --page-size 20
python3 client.py orders --where H --start-date 2026-02-01 --end-date 2026-03-01
python3 client.py order-no-complete
python3 client.py order-no-complete --any --json
```
### 示例 6:订票(预检与提交)
```bash
# 只校验,不最终提交
python3 client.py book --date 2026-03-23 --from 北京南 --to 上海虹桥 --train-code G101 --seat second_class --passengers 张三 --dry-run
# 正式提交
python3 client.py book --date 2026-03-23 --from 北京南 --to 上海虹桥 --train-code G101 --seat second_class --passengers 张三
# 单人选座(D 会自动归一化为 1D)
python3 client.py book --date 2026-03-23 --from 北京南 --to 上海虹桥 --train-code G101 --seat second_class --passengers 张三 --choose-seats D
# 不下单,仅获取订单支付信息(普通/中转通用)
python3 client.py order-pay --pay-channel alipay
```
### 示例 7:候补查询
```bash
# 候补排队状态
python3 client.py candidate-queue
# 候补订单(进行中)
python3 client.py candidate-orders
# 候补订单(已处理)
python3 client.py candidate-orders --processed --start-date 2026-03-11 --end-date 2026-04-09 --limit 20
# 提交候补(建议目标席别余票为“无”时)
python3 client.py candidate-submit --date 2026-03-23 --from 北京南 --to 上海虹桥 --train-code G101 --seat second_class
# 取消候补
python3 client.py candidate-cancel --reserve-no <候补单号>
# 候补支付参数(自动读取 reserve_no)
python3 client.py candidate-pay
# 候补支付参数(指定 reserve_no)
python3 client.py candidate-pay --reserve-no <候补单号>
```
## 每个命令参数说明
### 全局参数(所有命令可用)
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--timeout` | 否 | `15` | 请求超时时间(秒) |
| `--json` | 否 | 关闭 | 以 JSON 输出结果 |
### `left-ticket` 余票查询
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--date` | 是 | 无 | 出发日期,`YYYY-MM-DD` |
| `--from` | 是 | 无 | 出发站(中文/拼音/三字码) |
| `--to` | 是 | 无 | 到达站(中文/拼音/三字码) |
| `--purpose` | 否 | `ADULT` | 乘客类型 |
| `--endpoint` | 否 | `queryG` | 余票接口类型,`queryG` 或 `queryZ` |
| `--limit` | 否 | `20` | 文本输出时最多展示行数 |
### `transfer-ticket` 中转换乘
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--date` | 是 | 无 | 出发日期,`YYYY-MM-DD` |
| `--from` | 是 | 无 | 出发站 |
| `--to` | 是 | 无 | 到达站 |
| `--middle` | 否 | 空 | 指定换乘站,不传则自动推荐 |
| `--result-index` | 否 | `0` | 分页游标 |
| `--can-query` | 否 | `Y` | 是否继续查询更多方案(`Y/N`) |
| `--show-wz` | 否 | 关闭 | 显示无座方案 |
| `--purpose` | 否 | `00` | 中转接口乘客类型参数 |
| `--channel` | 否 | `E` | 中转接口渠道参数 |
| `--endpoint` | 否 | `queryG` | 中转接口类型,`queryG` 或 `queryZ` |
| `--limit` | 否 | `20` | 文本输出时最多展示方案数 |
### `transfer-book` 提交中转订单
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--date` | 是 | 无 | 出发日期,`YYYY-MM-DD` |
| `--from` | 是 | 无 | 出发站 |
| `--to` | 是 | 无 | 到达站 |
| `--middle` | 否 | 空 | 指定换乘站,不传则自动推荐 |
| `--plan-index` | 否 | `1` | 选择第几个中转方案(从 1 开始) |
| `--result-index` | 否 | `0` | 中转查询分页游标 |
| `--can-query` | 否 | `Y` | 是否继续查询更多方案(`Y/N`) |
| `--show-wz` | 否 | 关闭 | 显示无座方案 |
| `--seat` | 是 | 无 | 席别(如 `second_class` / `O` / `一等座`) |
| `--passengers` | 是 | 无 | 乘客姓名,多个用逗号分隔 |
| `--purpose` | 否 | `00` | 中转乘客类型编码 |
| `--channel` | 否 | `E` | 中转接口渠道参数 |
| `--endpoint` | 否 | `queryG` | 中转接口类型(`queryG/queryZ`) |
| `--max-wait-seconds` | 否 | `30` | 排队轮询最长等待秒数 |
| `--poll-interval` | 否 | `1.5` | 排队轮询间隔(秒) |
| `--dry-run` | 否 | 关闭 | 只检查不提交最终确认 |
### `route` 经停站查询
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--train-code` | 二选一 | 无 | 车次号(如 `C956`、`G1033`),会自动解析 `train_no` |
| `--train-no` | 二选一 | 无 | 内部车次号(如 `760000C95604`) |
| `--date` | 是 | 无 | 查询日期,`YYYY-MM-DD` |
| `--from` | 是 | 无 | 区间出发站 |
| `--to` | 是 | 无 | 区间到达站 |
| `--endpoint` | 否 | `queryG` | 仅 `--train-code` 模式下用于解析 `train_no` |
| `--purpose` | 否 | `ADULT` | 仅 `--train-code` 模式下用于解析 `train_no` |
| `--limit` | 否 | `200` | 文本输出时最多展示站点数 |
### `login` 登录
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--username` | 是 | 无 | 12306 用户名/邮箱/手机号 |
| `--password` | 否 | 交互输入或 `KYFW_PASSWORD` | 登录密码 |
| `--id-last4` | 否 | 无 | 证件号后 4 位,短信验证场景需要 |
| `--sms-code` | 否 | 无 | 6 位短信验证码 |
| `--send-sms` | 否 | 关闭 | 仅发送短信验证码,不执行完整登录 |
### `status` 登录状态检查
无专属参数,仅使用全局参数。
### `qr-login-create` 生成二维码登录图片(自动后台检查,不阻塞)
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--appid` | 否 | `otn` | 二维码登录 appid |
### `passengers` 乘车人查询
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--limit` | 否 | `200` | 文本输出最多展示人数 |
### `orders` 订单查询
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--where` | 否 | `G` | `G` 未出行/近期,`H` 历史订单 |
| `--start-date` | 否 | 自动计算 | 查询起始日期,`YYYY-MM-DD` |
| `--end-date` | 否 | 今天(`--where H` 时为昨天) | 查询结束日期,`YYYY-MM-DD`;历史订单场景必须早于今天 |
| `--page-index` | 否 | `0` | 页码 |
| `--page-size` | 否 | `8` | 每页条数 |
| `--query-type` | 否 | `1` | 查询类型:`1` 按订票日期,`2` 按乘车日期 |
| `--train-name` | 否 | 空 | 按订单号/车次/姓名筛选(对应接口字段 `sequeue_train_name`) |
### `order-no-complete` 查询 1 条未完成订单
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--any` | 否 | 关闭 | 默认仅返回可支付订单(`pay_flag=Y`);开启后返回第一条未完成订单 |
### `candidate-queue` 候补排队状态
无专属参数,仅使用全局参数。
### `candidate-orders` 候补订单查询
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--processed` | 否 | 关闭 | 查询已处理候补订单;默认查询进行中 |
| `--page-no` | 否 | `0` | 页码 |
| `--start-date` | 否 | 今天 | 查询起始日期,`YYYY-MM-DD` |
| `--end-date` | 否 | 起始日期+29天 | 查询结束日期,`YYYY-MM-DD` |
| `--limit` | 否 | `20` | 文本输出最多展示条数 |
### `candidate-submit` 提交候补订单
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--date` | 是 | 无 | 出发日期,`YYYY-MM-DD` |
| `--from` | 是 | 无 | 出发站 |
| `--to` | 是 | 无 | 到达站 |
| `--train-code` | 是 | 无 | 目标车次(如 `G101`) |
| `--seat` | 是 | 无 | 席别(如 `second_class` / `O` / `一等座`) |
| `--passengers` | 否 | 空 | 乘客姓名,多个用逗号分隔;不传时默认选首位乘车人 |
| `--purpose` | 否 | `ADULT` | 乘客类型 |
| `--endpoint` | 否 | `queryG` | 余票接口类型 |
| `--force` | 否 | 关闭 | 即使余票不是“无”也尝试提交候补 |
| `--max-wait-seconds` | 否 | `30` | 候补排队轮询最长等待秒数 |
| `--poll-interval` | 否 | `1.0` | 候补排队轮询间隔秒数 |
说明:当前实现会继续执行候补确认与排队查询;若超时会返回“仍在排队中”,可继续用 `candidate-orders`/`candidate-queue` 查看。
### `candidate-cancel` 取消候补订单
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--reserve-no` | 是 | 无 | 候补单号(reserve_no) |
### `candidate-pay` 候补支付参数获取
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--reserve-no` | 否 | 自动读取 | 候补单号;不传则尝试从 `candidate-queue` 自动读取 |
| `--pay-channel` | 否 | 空 | 支付渠道:`alipay` / `wechat` / `unionpay` |
### `order-pay` 订单支付参数(不下单,普通/中转通用)
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--pay-channel` | 否 | 空 | 支付渠道:`alipay` / `wechat` / `unionpay` |
### `book` 订票
| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `--date` | 是 | 无 | 出发日期,`YYYY-MM-DD` |
| `--from` | 是 | 无 | 出发站 |
| `--to` | 是 | 无 | 到达站 |
| `--train-code` | 是 | 无 | 目标车次(如 `G101`) |
| `--seat` | 是 | 无 | 席别(如 `second_class` / `O` / `一等座`) |
| `--passengers` | 是 | 无 | 乘客姓名,多个用逗号分隔 |
| `--purpose` | 否 | `ADULT` | 乘客类型 |
| `--endpoint` | 否 | `queryG` | 余票接口类型 |
| `--choose-seats` | 否 | 空 | 选座(如 `1D`;单人可传 `D`) |
| `--max-wait-seconds` | 否 | `30` | 排队轮询最长等待秒数 |
| `--poll-interval` | 否 | `1.5` | 排队轮询间隔(秒) |
| `--dry-run` | 否 | 关闭 | 只检查不提交最终确认 |
## 参数提取规则
- 出发站:`--from`
- 到达站:`--to`
- 日期:`--date`(格式 `YYYY-MM-DD`)
- 经停场景:用户给车次号(如 `G1033`、`C956`)时用 `--train-code`
- 经停场景:用户给内部号(如 `760000C95604`)时用 `--train-no`
- 查询区间优先用用户提供的 `from/to`
## 输出策略
- 默认输出文本结果并概括关键信息。
- 若用户说“返回 JSON / 机器可读”,添加 `--json` 并返回结构化摘要。
- `book`/`transfer-book` 成功时应突出 `order_id`,并提示用户执行 `order-pay` 获取支付参数。
## 示例工作流
### 示例 A:余票
用户:“查明天北京到上海余票”
```bash
python3 client.py left-ticket --date <明天日期> --from 北京 --to 上海
```
### 示例 B:经停站
用户:“C956 经停哪些站”
如果用户未给日期或区间,先补齐最小参数(日期、from、to);拿到后执行:
```bash
python3 client.py route --train-code C956 --date <日期> --from <出发站> --to <到达站>
```
### 示例 C:中转
用户:“深圳到拉萨怎么中转”
```bash
python3 client.py transfer-ticket --date <日期> --from 深圳 --to 拉萨 --limit 10
```
### 示例 C.1:中转下单
用户:“把第1个中转方案给我下单,二等座,乘客张三”
```bash
python3 client.py transfer-book --date <日期> --from <出发站> --to <到达站> --plan-index 1 --seat second_class --passengers 张三
# 下单成功后,单独获取支付参数/二维码
python3 client.py order-pay --pay-channel alipay
```
### 示例 D:候补
用户:“帮我看看候补订单有没有兑现”
```bash
python3 client.py candidate-orders --processed --start-date <起始日期> --end-date <结束日期> --limit 20
```
## 限制与注意
1. 中转结果来自 12306 推荐,不保证覆盖所有可行组合。
2. 可能触发风控(如 `error.html`),需提示用户稍后重试或降低频率。
3. 订票链路依赖登录态与乘车人信息,建议先 `status`/`passengers`。
4. 相对日期必须换算成绝对日期再执行命令。
5. 支付阶段统一走 `order-pay`;脚本会尝试返回支付二维码/链接;也要主动提示用户去 12306 App 的“待支付订单”支付。
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!