12306 CLI Skill 🚄
目标
用本仓库的 client.py 完成 12306 相关查询与下单辅助,优先覆盖:
- - 余票查询: INLINECODE1
- 中转换乘: INLINECODE2
- 中转下单: INLINECODE3
- 经停站:
route(支持 --train-code 自动解析) - 登录态检查: INLINECODE6
- 二维码登录: INLINECODE7
- 候补管理:
candidate-queue / candidate-orders / candidate-submit / candidate-cancel / INLINECODE12 - 支付信息: INLINECODE13
- 需要登录的操作:
passengers / orders / order-no-complete / book / transfer-book / order-pay / candidate-submit / candidate-cancel / INLINECODE22
触发信号
用户提到下列需求时触发本技能:
- - “查明天北京到上海余票”
- “G1033 经停站”
- “深圳到拉萨怎么中转”
- “把第1个中转方案下单”
- “候补排队状态怎么样”
- “12306 登录状态”
执行原则
- 1. 默认用
text 输出(便于用户阅读);仅在用户明确要求结构化数据时加 --json。 - 解析相对日期(今天/明天/后天)为
YYYY-MM-DD 后再执行命令。 - 站名支持中文/拼音/三字码,直接传给命令即可。
- INLINECODE26 优先用
--train-code,减少用户提供 train_no 的负担。 - 失败时先给出可执行修复建议(缺参数、日期格式、站名不匹配、风控限制等)。
- INLINECODE29 /
transfer-book 成功后优先告知订单号,并提示下一步执行 order-pay 获取支付参数;若网页支付不可用,建议去 12306 App 的“待支付订单”继续支付。 - INLINECODE32 会自动后台启动登录检查;扫码确认后统一用
status 判断是否已登录。
常用示例
示例 1:余票查询
CODEBLOCK0
示例 2:中转换乘
CODEBLOCK1
示例 2.1:中转下单
CODEBLOCK2
示例 3:经停站
CODEBLOCK3
示例 4:登录与状态
CODEBLOCK4
示例 5:乘车人与订单
CODEBLOCK5
示例 6:订票(预检与提交)
CODEBLOCK6
示例 7:候补查询
CODEBLOCK7
每个命令参数说明
全局参数(所有命令可用)
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE34 | 否 | INLINECODE35 | 请求超时时间(秒) |
| INLINECODE36 |
否 | 关闭 | 以 JSON 输出结果 |
left-ticket 余票查询
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE38 | 是 | 无 | 出发日期, INLINECODE39 |
| INLINECODE40 |
是 | 无 | 出发站(中文/拼音/三字码) |
|
--to | 是 | 无 | 到达站(中文/拼音/三字码) |
|
--purpose | 否 |
ADULT | 乘客类型 |
|
--endpoint | 否 |
queryG | 余票接口类型,
queryG 或
queryZ |
|
--limit | 否 |
20 | 文本输出时最多展示行数 |
transfer-ticket 中转换乘
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE51 | 是 | 无 | 出发日期, INLINECODE52 |
| INLINECODE53 |
是 | 无 | 出发站 |
|
--to | 是 | 无 | 到达站 |
|
--middle | 否 | 空 | 指定换乘站,不传则自动推荐 |
|
--result-index | 否 |
0 | 分页游标 |
|
--can-query | 否 |
Y | 是否继续查询更多方案(
Y/N) |
|
--show-wz | 否 | 关闭 | 显示无座方案 |
|
--purpose | 否 |
00 | 中转接口乘客类型参数 |
|
--channel | 否 |
E | 中转接口渠道参数 |
|
--endpoint | 否 |
queryG | 中转接口类型,
queryG 或
queryZ |
|
--limit | 否 |
20 | 文本输出时最多展示方案数 |
transfer-book 提交中转订单
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE73 | 是 | 无 | 出发日期, INLINECODE74 |
| INLINECODE75 |
是 | 无 | 出发站 |
|
--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 经停站查询
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE104 | 二选一 | 无 | 车次号(如 C956、G1033),会自动解析 INLINECODE107 |
| INLINECODE108 |
二选一 | 无 | 内部车次号(如
760000C95604) |
|
--date | 是 | 无 | 查询日期,
YYYY-MM-DD |
|
--from | 是 | 无 | 区间出发站 |
|
--to | 是 | 无 | 区间到达站 |
|
--endpoint | 否 |
queryG | 仅
--train-code 模式下用于解析
train_no |
|
--purpose | 否 |
ADULT | 仅
--train-code 模式下用于解析
train_no |
|
--limit | 否 |
200 | 文本输出时最多展示站点数 |
login 登录
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE125 | 是 | 无 | 12306 用户名/邮箱/手机号 |
| INLINECODE126 |
否 | 交互输入或
KYFW_PASSWORD | 登录密码 |
|
--id-last4 | 否 | 无 | 证件号后 4 位,短信验证场景需要 |
|
--sms-code | 否 | 无 | 6 位短信验证码 |
|
--send-sms | 否 | 关闭 | 仅发送短信验证码,不执行完整登录 |
status 登录状态检查
无专属参数,仅使用全局参数。
qr-login-create 生成二维码登录图片(自动后台检查,不阻塞)
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE133 | 否 | INLINECODE134 | 二维码登录 appid |
passengers 乘车人查询
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE136 | 否 | INLINECODE137 | 文本输出最多展示人数 |
orders 订单查询
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE139 | 否 | INLINECODE140 | INLINECODE141 未出行/近期,H 历史订单 |
| INLINECODE143 |
否 | 自动计算 | 查询起始日期,
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 条未完成订单
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE159 | 否 | 关闭 | 默认仅返回可支付订单(pay_flag=Y);开启后返回第一条未完成订单 |
candidate-queue 候补排队状态
无专属参数,仅使用全局参数。
candidate-orders 候补订单查询
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE163 | 否 | 关闭 | 查询已处理候补订单;默认查询进行中 |
| INLINECODE164 |
否 |
0 | 页码 |
|
--start-date | 否 | 今天 | 查询起始日期,
YYYY-MM-DD |
|
--end-date | 否 | 起始日期+29天 | 查询结束日期,
YYYY-MM-DD |
|
--limit | 否 |
20 | 文本输出最多展示条数 |
candidate-submit 提交候补订单
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE173 | 是 | 无 | 出发日期, INLINECODE174 |
| INLINECODE175 |
是 | 无 | 出发站 |
|
--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 取消候补订单
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE196 | 是 | 无 | 候补单号(reserve_no) |
candidate-pay 候补支付参数获取
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE198 | 否 | 自动读取 | 候补单号;不传则尝试从 candidate-queue 自动读取 |
| INLINECODE200 |
否 | 空 | 支付渠道:
alipay /
wechat /
unionpay |
order-pay 订单支付参数(不下单,普通/中转通用)
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE205 | 否 | 空 | 支付渠道:alipay / wechat / INLINECODE208 |
book 订票
| 参数 | 必填 | 默认值 | 说明 |
|---|
| INLINECODE210 | 是 | 无 | 出发日期, INLINECODE211 |
| INLINECODE212 |
是 | 无 | 出发站 |
|
--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 | 否 | 关闭 | 只检查不提交最终确认 |
参数提取规则
- - 出发站: INLINECODE233
- 到达站: INLINECODE234
- 日期:
--date(格式 YYYY-MM-DD) - 经停场景:用户给车次号(如
G1033、C956)时用 INLINECODE239 - 经停场景:用户给内部号(如
760000C95604)时用 INLINECODE241 - 查询区间优先用用户提供的 INLINECODE242
输出策略
- - 默认输出文本结果并概括关键信息。
- 若用户说“返回 JSON / 机器可读”,添加
--json 并返回结构化摘要。 - INLINECODE244 /
transfer-book 成功时应突出 order_id,并提示用户执行 order-pay 获取支付参数。
示例工作流
示例 A:余票
用户:“查明天北京到上海余票”
CODEBLOCK8
示例 B:经停站
用户:“C956 经停哪些站”
如果用户未给日期或区间,先补齐最小参数(日期、from、to);拿到后执行:
CODEBLOCK9
示例 C:中转
用户:“深圳到拉萨怎么中转”
CODEBLOCK10
示例 C.1:中转下单
用户:“把第1个中转方案给我下单,二等座,乘客张三”
CODEBLOCK11
示例 D:候补
用户:“帮我看看候补订单有没有兑现”
CODEBLOCK12
限制与注意
- 1. 中转结果来自 12306 推荐,不保证覆盖所有可行组合。
- 可能触发风控(如
error.html),需提示用户稍后重试或降低频率。 - 订票链路依赖登录态与乘车人信息,建议先
status/passengers。 - 相对日期必须换算成绝对日期再执行命令。
- 支付阶段统一走
order-pay;脚本会尝试返回支付二维码/链接;也要主动提示用户去 12306 App 的“待支付订单”支付。
12306 CLI 技能 🚄
目标
使用本仓库的 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。
- 解析相对日期(今天/明天/后天)为 YYYY-MM-DD 后再执行命令。
- 站名支持中文/拼音/三字码,直接传给命令即可。
- route 优先使用 --train-code,减少用户提供 train_no 的负担。
- 失败时先给出可执行的修复建议(缺少参数、日期格式、站名不匹配、风控限制等)。
- book/transfer-book 成功后优先告知订单号,并提示下一步执行 order-pay 获取支付参数;若网页支付不可用,建议前往 12306 App 的待支付订单继续支付。
- 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 | 文本