12306 官方数据查询方案 ⭐⭐⭐⭐⭐
💡 核心思路
用户建议:直接用 12306 查询,固定查 7 天后的车次,不屏蔽无票车次,获取完整时刻表
优势:
- ✅ 数据最权威(官方源)
- ✅ 完全免费
- ✅ 实时更新
- ✅ 无需 API Key
- ✅ 无调用限制
🎯 查询策略
为什么查 7 天后?
| 时间 | 放票状态 | 适合用途 |
|---|---|---|
| 当天 | 部分车次售罄 | ❌ 不适合 |
| 3 天后 | 热门车次售罄 | ❌ 不适合 |
| 7 天后 | 大部分车次有票 | ✅ 最佳 |
| 15 天后 | 全部车次可查 | ✅ 很好 |
| 30 天后 | 未放票 | ❌ 无数据 |
12306 放票规则:
- 提前 15 天放票(含当天)
- 查 7 天后 = 第 8 天的车次
- 此时大部分车次已放票,且未售罄
为什么不屏蔽无票车次?
目的:获取完整时刻表,而非实际购票
| 筛选方式 | 结果 | 适用场景 |
|---|---|---|
| 只显示有票 | 遗漏部分车次 | ❌ 不适合时刻表收集 |
| 显示全部车次 | 完整时刻表 | ✅ 适合 |
🔧 实现方案
方案一:浏览器自动化(推荐)
工具:Playwright / Selenium
流程:
- 打开 12306 官网
- 输入出发站、到达站
- 选择 7 天后的日期
- 不勾选"只看有票"
- 爬取结果页面
- 解析车次信息
- 存储到本地数据库
优点:
- 数据最准确
- 无需 API Key
- 完全免费
缺点:
- 需要浏览器环境
- 可能有验证码
- 速度较慢
示例代码:
from playwright.sync_api import sync_playwright
def query_12306(from_station, to_station, date):
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 访问 12306
page.goto("https://www.12306.cn")
# 输入查询条件
page.fill("#fromStationText", from_station)
page.fill("#toStationText", to_station)
page.fill("#train_date", date)
# 不勾选"只看有票"
page.uncheck("#checkbox_show_ticket")
# 点击查询
page.click("#query_ticket")
# 等待结果
page.wait_for_selector("#result-list")
# 解析结果
trains = page.query_selector_all(".train-list")
for train in trains:
train_no = train.query_selector(".train-number").text_content()
from_time = train.query_selector(".start-time").text_content()
to_time = train.query_selector(".arrive-time").text_content()
# ... 保存数据
browser.close()
方案二:12306 接口(技术向)
接口地址:
https://kyfw.12306.cn/otn/leftTicket/query
参数:
-
leftTicketDate: 查询日期 -
from_station: 出发站代码 -
to_station: 到达站代码 -
purpose_codes: ADULT(成人票)
优点:
- 速度快
- 无需浏览器
缺点:
- 需要 Cookie 和验证码
- 反爬严格
- 需要维护登录态
不推荐普通用户使用
方案三:第三方接口(备选)
如果 12306 直连困难,使用:
- 聚合数据:https://www.juhe.cn
- 阿里云市场:https://market.aliyun.com
优点:
- 稳定可靠
- 有免费额度
缺点:
- 需要 API Key
- 有调用限制
📊 数据收集策略
热门线路优先
第一批(10 条):
北京→西安
北京→上海
北京→广州
北京→成都
北京→重庆
上海→杭州
上海→南京
广州→深圳
西安→宝鸡
西安→汉中
第二批(20 条):
省会城市之间的高铁线路
第三批(50 条):
省内主要城市线路
查询频率
| 策略 | 频率 | 说明 |
|---|---|---|
| 保守 | 1 次/3 秒 | 避免触发风控 |
| 正常 | 1 次/2 秒 | 推荐 |
| 激进 | 1 次/1 秒 | 可能触发验证码 |
💾 数据存储
数据库结构
-- 车次表
CREATE TABLE trains (
id INTEGER PRIMARY KEY,
train_no TEXT, -- 车次号(如 G655)
from_station TEXT, -- 出发站
to_station TEXT, -- 到达站
departure_time TEXT, -- 出发时间
arrival_time TEXT, -- 到达时间
duration TEXT, -- 历时
distance INTEGER, -- 里程
query_date TEXT, -- 查询日期
created_at TIMESTAMP -- 创建时间
);
-- 站点表
CREATE TABLE stations (
id INTEGER PRIMARY KEY,
station_name TEXT, -- 站点名称
station_code TEXT, -- 站点代码(如 VNP)
city_name TEXT, -- 城市名
province TEXT -- 省份
);
-- 查询记录表
CREATE TABLE query_log (
id INTEGER PRIMARY KEY,
from_station TEXT,
to_station TEXT,
query_date TEXT,
result_count INTEGER,
created_at TIMESTAMP
);
缓存策略
| 数据类型 | 缓存时间 | 说明 |
|---|---|---|
| 时刻表 | 7 天 | 车次时刻相对稳定 |
| 票价 | 1 天 | 可能浮动 |
| 余票 | 实时 | 变化频繁 |
🚀 实施步骤
步骤 1:创建查询脚本
cd /root/.openclaw/workspace/travel/scripts/train_schedule
touch query_12306.py
步骤 2:安装依赖
pip install playwright
playwright install chromium
步骤 3:编写脚本
参考上面的示例代码
步骤 4:测试查询
python query_12306.py --from 北京 --to 西安 --date 2026-03-21
步骤 5:批量收集
# 创建批量查询脚本
touch batch_query.sh
# 查询热门线路
./batch_query.sh
⚠️ 注意事项
1. 遵守规则
- 不要高频查询(建议间隔 2-3 秒)
- 不要多线程并发
- 遵守 robots.txt
2. 验证码处理
- 遇到验证码时暂停
- 可考虑使用打码平台
- 或切换 IP
3. 数据准确性
- 12306 数据最权威
- 但仍建议在购票前再次核实
- 标注"具体车次请以 12306 查询为准"
4. 法律风险
- 仅用于个人旅行规划
- 不要商业化使用
- 不要大规模爬取
📈 与 API 方案对比
| 特性 | 12306 直连 | 第三方 API |
|---|---|---|
| 数据准确性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 成本 | 免费 | 免费/付费 |
| 稳定性 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 易用性 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 限制 | 可能有验证码 | 调用次数限制 |
| 推荐度 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
🎯 推荐方案
个人使用(推荐 12306 直连)
场景:规划自己的旅行
方案:
- 手动在 12306 App 查询
- 记录车次信息
- 写入行程规划
优点:
- 最简单
- 无需编程
- 数据准确
批量收集(推荐 API)
场景:建立完整时刻表数据库
方案:
- 使用聚合数据 API
- 批量查询热门线路
- 缓存到本地
优点:
- 稳定可靠
- 易于自动化
- 无验证码
混合方案(最佳)
日常使用:
- 12306 App 手动查询
- 记录到行程规划
数据积累:
- API 批量查询
- 建立本地数据库
📝 下一步
-
确认需求:
- 个人使用 → 12306 App 手动查询
- 批量收集 → 聚合数据 API
-
选择方案:
- 简单 → 手动查询
- 自动化 → API
- 开始实施
创建日期:2026-03-14 维护者:Travel Agent