上周去接人,只知道车次 G1234,想知道几点到站。12306 App 点两下就能看到,但要写进自己的小程序就得对接数据。折腾一晚上才发现,难点不在接口地址,而在那个看着像时间、其实不是时间的字段。
车次时刻接口长什么样
常用的是 czxx 下的 queryByTrainNo,需要三个参数:train_no、from_station_telecode、to_station_telecode。train_no 不是车次号,是一串内部编码,得先从余票查询接口拿到。车站电报码是三字母,比如北京南是 VNP,上海虹桥是 AOH。
GET https://kyfw.12306.cn/otn/czxx/queryByTrainNo?train_no=240000G12340&from_station_telecode=VNP&to_station_telecode=AOHarrive_time 是相对始发站的分钟数
返回的 JSON 里每个站有 arrive_time 和 start_time,乍看像时间,实际是距离始发站发车的分钟偏移。G1234 始发 08:00,某站 arrive_time 是 143,实际到站就是 10:23。不换算直接显示,界面上会是一堆 00:00 和 02:23 这种鬼东西。始发时间要从车次基本信息里取 start_time,再自己加。
跨天要单独处理
过夜车的偏移会超过 1440,直接对 24 取模会丢掉「次日」信息。做法是保留总分钟数,展示时算 dayOffset 等于总分钟数除以 1440 取整,再拼上「次日」「第三日」。另外接口给的都是北京时间,服务器跑在 UTC 时区别直接拿本地时间硬套。
频率限制和证书两个坑
站点有频控,几百毫秒一次连续请求会返回空内容或者跳验证页,间隔放到一秒以上比较稳。https 证书链在部分老版本 curl 上校验失败,别图省事关掉校验,把根证书补全就行。数据只做展示问题不大,做商业查询服务要看清条款。
更省事的替代方案
只是自己看,直接解析分享页或者车站大屏的公开数据更简单,字段就是现成的时间。要长期稳定使用,老老实实走开放平台的接口,别把爬虫当生产方案,改版一次就得重写。
取舍:要准就别怕慢,加缓存、错开请求间隔;要快就用官方授权接口。图省事抓页面,接口一改版就得重来。