12306 余票查询API浅探索
程序员文章站
2024-03-17 21:56:04
...
12306 余票查询API浅探索
余票查询请求分析
点击查询,F12进入控制台,进入NetWork面板,查看发送的请求:
点入请求查看详情,很明显,查询请求是第二条:
查看请求Response:
的确拿到了数据,不过好像有什么不对:
数据好像做了什么处理,看不懂哦。想来应该是用JS解密的,OK,JS调试走起。
响应数据解密代码查找调试
回到NetWork面板,鼠标移到请求URL上,查看请求发起程序:
点进去,直接定位到调用程序,设置断点:
重新点击查询,开始逐步调试,调试过程要注意跟踪变量,最终会来到这一段程序:
很显然,function cr(cQ, cS)就是执行将响应数据进行解密的程序,其中cQ,cS参数分别是:
对应加密数据集合:
始发车站和终点车站字典:
程序源代码如下:
function cr(cQ, cS) {
var cP = [];
for (var cO = 0; cO < cQ.length; cO++) {
var cT = [];
var cN = cQ[cO].split("|");
cT.secretStr = cN[0];
cT.buttonTextInfo = cN[1];
var cR = [];
cR.train_no = cN[2];
cR.station_train_code = cN[3];
cR.start_station_telecode = cN[4];
cR.end_station_telecode = cN[5];
cR.from_station_telecode = cN[6];
cR.to_station_telecode = cN[7];
cR.start_time = cN[8];
cR.arrive_time = cN[9];
cR.lishi = cN[10];
cR.canWebBuy = cN[11];
cR.yp_info = cN[12];
cR.start_train_date = cN[13];
cR.train_seat_feature = cN[14];
cR.location_code = cN[15];
cR.from_station_no = cN[16];
cR.to_station_no = cN[17];
cR.is_support_card = cN[18];
cR.controlled_train_flag = cN[19];
cR.gg_num = cN[20] ? cN[20] : "--";
cR.gr_num = cN[21] ? cN[21] : "--";
cR.qt_num = cN[22] ? cN[22] : "--";
cR.rw_num = cN[23] ? cN[23] : "--";
cR.rz_num = cN[24] ? cN[24] : "--";
cR.tz_num = cN[25] ? cN[25] : "--";
cR.wz_num = cN[26] ? cN[26] : "--";
cR.yb_num = cN[27] ? cN[27] : "--";
cR.yw_num = cN[28] ? cN[28] : "--";
cR.yz_num = cN[29] ? cN[29] : "--";
cR.ze_num = cN[30] ? cN[30] : "--";
cR.zy_num = cN[31] ? cN[31] : "--";
cR.swz_num = cN[32] ? cN[32] : "--";
cR.srrb_num = cN[33] ? cN[33] : "--";
cR.yp_ex = cN[34];
cR.seat_types = cN[35];
cR.exchange_train_flag = cN[36];
cR.houbu_train_flag = cN[37];
cR.houbu_seat_limit = cN[38];
cR.from_station_name = cS[cN[6]];
cR.to_station_name = cS[cN[7]];
cT.queryLeftNewDTO = cR;
cP.push(cT)
}
return cP
}
这段代码将用"|"连接的字符串数据进行分割,然后提取出段数据按照规则拼成新的JSON格式的数据,只是代码经过编译,不太好读。
数据说明
经过解密的数据最终是这个样子的:
{
"buttonTextInfo": "预订",
"queryLeftNewDTO": {
"arrive_time": "22:28",
"canWebBuy": "Y",
"controlled_train_flag": "0",
"end_station_telecode": "BXP",
"exchange_train_flag": "1",
"from_station_name": "广州南",
"from_station_no": "01",
"from_station_telecode": "IZQ",
"gg_num": "--",
"gr_num": "--",
"houbu_seat_limit": "",
"houbu_train_flag": "0",
"is_support_card": "1",
"lishi": "09:38",
"location_code": "Q7",
"qt_num": "--",
"rw_num": "--",
"rz_num": "--",
"seat_types": "OM9",
"srrb_num": "--",
"start_station_telecode": "IZQ",
"start_time": "12:50",
"start_train_date": "20191222",
"station_train_code": "G70",
"swz_num": "3",
"to_station_name": "北京西",
"to_station_no": "16",
"to_station_telecode": "BXP",
"train_no": "6c00000G700E",
"train_seat_feature": "3",
"tz_num": "--",
"wz_num": "--",
"yb_num": "--",
"yp_ex": "O0M090",
"yp_info": "GUrhKYs66fa4Qkmv0jeRFrWl6He53Xjen59rMW556V4Bo2s7",
"yw_num": "--",
"yz_num": "--",
"ze_num": "有",
"zy_num": "10"
},
"secretStr": "wQABjQbR9E%2Fn6hMLNSUP6p6v6djwCvahYS2xqJZ7ZB5mKfmzHhzudmjZD9TZm66N%2FpURPPvcFZS1%0A%2FO6bVpeIcPuevb3Xsf4x%2FJTLu6CUi4SonvPoO7TUT8ip85ZmS1mELs3nIIka%2Fx4wp%2FyNIcw%2FFj1F%0Ae2VPTbVjzxUl2i%2B5QffvnWvjjTVe39PXgJGzZVJzMU8tzTdzTkhr5ZFG%2BxfQ9X3PeEyPVE79hk46%0Amesr%2FmsV6M8AiH%2FTKPtxIYUiV9K7DwUlTPZP%2F%2FnV8TKjO7wiS0QQ95NQv9XyKqcw58OJ7UnAn0iH%0A"
}
这里面大多字段都是代码以及缩写,不过还是可以判断出一些有用字段:
{
"buttonTextInfo": "预订", => 按钮文字
"queryLeftNewDTO": { => 主要数据结构
"arrive_time": "22:28", => 列车到达时间
"canWebBuy": "Y", => 是否支持网上购票
"controlled_train_flag": "0", =>
"end_station_telecode": "BXP", =>
"exchange_train_flag": "1", =>
"from_station_name": "广州南", => 列车始发站
"from_station_no": "01",
"from_station_telecode": "IZQ",
"gg_num": "--",
"gr_num": "--",
"houbu_seat_limit": "", => 候补车票余量
"houbu_train_flag": "0", => 是否支持候补
"is_support_card": "1",
"lishi": "09:38", => 历时(列车运行时间)
"location_code": "Q7",
"qt_num": "--",
"rw_num": "--",
"rz_num": "--",
"seat_types": "OM9",
"srrb_num": "--",
"start_station_telecode": "IZQ",
"start_time": "12:50", => 发车时间
"start_train_date": "20191222", => 发车日期
"station_train_code": "G70", => 列车编号
"swz_num": "3",
"to_station_name": "北京西", => 终点站
"to_station_no": "16",
"to_station_telecode": "BXP",
"train_no": "6c00000G700E", => 列车识别号
"train_seat_feature": "3",
"tz_num": "--",
"wz_num": "--",
"yb_num": "--",
"yp_ex": "O0M090",
"yp_info": "GUrhKYs66fa4Qkmv0jeRFrWl6He53Xjen59rMW556V4Bo2s7",
"yw_num": "--", => 硬卧
"yz_num": "--", => 硬座
"ze_num": "有",
"zy_num": "10"
},
"secretStr": => 加密字符串 "wQABjQbR9E%2Fn6hMLNSUP6p6v6djwCvahYS2xqJZ7ZB5mKfmzHhzudmjZD9TZm66N%2FpURPPvcFZS1%0A%2FO6bVpeIcPuevb3Xsf4x%2FJTLu6CUi4SonvPoO7TUT8ip85ZmS1mELs3nIIka%2Fx4wp%2FyNIcw%2FFj1F%0Ae2VPTbVjzxUl2i%2B5QffvnWvjjTVe39PXgJGzZVJzMU8tzTdzTkhr5ZFG%2BxfQ9X3PeEyPVE79hk46%0Amesr%2FmsV6M8AiH%2FTKPtxIYUiV9K7DwUlTPZP%2F%2FnV8TKjO7wiS0QQ95NQv9XyKqcw58OJ7UnAn0iH%0A"
}
其他字段,大家可以自己对比界面进行推测,最后的secretStr加密字符串目前不知道是什么,不过感觉像是查询列车详情需要的密匙。不过,拥有这些信息已经足够用Python写一个自己的余票查询小程序了。有没有什么想法. . . . . .
上一篇: C++——STL学习①各种增加元素