前言
航空、铁路、高速三种交通方式中要数铁路的性价比最高了,周边城市来回比高速通畅又比航空实惠,但是逢年过节探亲或旅游要是忘了提前买票,想着当天买当天走是不太现实的,这时候估计只剩下三更半夜出发的票或者站票,令人难受。
于是我想着写个监控程序用于节假日来临提前通知我买票。
对于 12306 的票务系统我是早有耳闻的,其高并发处理能力堪称业界标杆,反爬机制也是强悍,但我只是查个票,又不需要抢票,应该没什么难度吧?
打开 PostMan 模拟 GET 请求,返回 “网络可能存在问题,请您重试一下!”,很好,我已经知道答案了。
探索
获取cookie
F12 打开开发者工具发现,12306 的查询请求是需要 cookie 的,我就纳闷了,我又没登陆哪来的 cookie ?看来技术菜也是出行困难的原因之一,百度一番之后才知道原来访问一次 12306 会自动生成 cookie ,而后台校验的则是 cookie 里边的一个具有时效性的 RAIL_DEVICEID
。至于如何得到 RAIL_DEVICEID
,我参照网上大神写的相关文章进行复现,但并未成功,其文章发表日期距今已有一年之余,估计 12306 已经更新了算法(或者是我操作姿势不对?)。
参考资料:
https://www.cnblogs.com/snowdreams1006/p/12316951.html
https://www.cnblogs.com/snowdreams1006/p/12320945.html
https://www.cnblogs.com/snowdreams1006/p/12325203.html
思来想去,我还是决定用最笨的也是开发效率最高的方式去获取 cookie ,祭出爬虫界元老级工具 —— Selenium
。
模拟查询
请求地址(需带 cookie ): https://kyfw.12306.cn/otn/leftTicket/queryT
请求方式:GET
示例:https://kyfw.12306.cn/otn/leftTicket/queryT?leftTicketDTO.train_date=0000-00-00&leftTicketDTO.from_station=XXX&leftTicketDTO.to_station=XXX&purpose_codes=ADULT
请求成功会返回一串带有余票信息的 Json。
请求参数 | 参数说明 |
---|---|
leftTicketDTO.train_date | 出发日期(格式:yyyy-mm-dd) |
leftTicketDTO.from_station | 出发站代码(查看代码) |
leftTicketDTO.to_station | 到达站代码(查看代码) |
purpose_codes | 乘客类型(成人:ADULT,学生:0X00) |
获取正确请求地址
查询余票的地址每天都会更换,所以在模拟查询的时候,如果请求的是旧的地址,那么会 302 跳转返回一个新的请求地址,前提是所带 cookie 是正确的。
响应参数 | 参数说明 |
---|---|
c_url | 新请求地址 |
c_name | 固定值:CLeftTicketUrl |
status | 不知道是什么状态 |