警告: 本程序是出于学习目的, 仅限于分析研究时用, 不可用于非法用途
由于程序所造成的损失本人概不负责, 如有造成不便请通知本人删除程序
欢迎大家去[GitHub Gist](https://gist.github.com/4554460)围观提提意见, 非常感谢
希望每个人都能买到回家的车票, 合家团圆...
http://www.douban.com/note/258531479//**
* 获取12306余票信息
*
* 查询列车的余票信息
* GET
https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getQueueCount&train_date=2013-02-05&train_no=240000D31307&station=D313&from=VNP&to=SHH *
* URL参数解析
* train_date // 不用说了吧
* train_no // 列车ID, 在余票查询结果车次的span中可以得到
* station // 车次
* from // 发站CODE 参考: dynamic.12306.cn/otsweb/js/common/station_name.js?version=5.42
* to // 到站CODE
*
* 返回数据
* {"countT":0,"count":116,"ticket":"1*****31794*****00001*****00943*****0001","op_1":true,"op_2":false}
* op_2=true -> 目前排队人数已经超过余票张数,请您选择其他席别或车次,特此提醒。
* countT -> 目前排队人数
* ticket -> 余票信息
*
* @
param 同URL参数, 都是必要参数, 外加一个seat参数(席别)
* 例如:
* get12306RemainTicket({
* train_date: "2013-02-02",
* train_no: '240000T1090G',
* station: 'T109',
* from: 'VNP',
* to: 'SHH',
* seat: 1
* });
*/
function get12306RemainTicket(param) {
var seat = param.seat;
delete param.seat;
$.ajax({
url: 'https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getQueueCount', // 必须HTTPS
type: 'GET',
data: param,
dataType: 'json',
success: function(data) {
console.log(data);
console.log(getTicketCountDesc(data.ticket, seat));
},
error: function() {
console.error(arguments);
}
});
}
/**
* 解密12306预订按钮(链接)代表什么含义
* 解密ypInfoDetail
*
* @
author Sun
* @
version 1.0 2013-1-17
*
* @
param mark 上面返回数据中的ticket, 也就是ypInfoDetail(查看余票查询结果中预订链接的内容)
* mark规律解析
* 1*****31794*****00001*****00943*****0001按照10个字符串为一组信息, 因此拆分如下
* 1*****3179
* 4*****0000
* 1*****0094
* 3*****0001
* 星号前面的第一位为席别, 星号后面的为余票数, 如果这个数字大于3000则表示无座票, 应减去3000后才是真正的余票数
* 因此总体规律为 -> 席别*****余票数
* @
param seat 席别类型(硬座: 1, 硬卧: 3, 软卧: 4), 在预订页面中获取$("#passenger_1_seat").val()
* @
see dynamic.12306.cn/otsweb/js/order/save_passenger_info.js?version=5.42
*/
function getTicketCountDesc(mark, seat) {
var ticketCountDesc = "";
// 本次列车您选择的席别尚有余票94张
var seatTicket = -1; // 所选席别余票多少张
// 无座179张
var withoutSeatTicket = -1; // 无座票多少张
var i = 0;
while (i < mark.length) {
// 1*****3179
var group = mark.substr(i, 10);
// 1(席别)
var seatType = group.substr(0, 1);
// 1 == 1(硬座)
if (seatType == seat) {
// 3179
var count = group.substr(6, 4);
while (count.length > 1 && count.substr(0, 1) == "0") { // count为0000的情况, count最终等于0
count = count.substr(1, count.length);
}
// 3179
count = parseInt(count);
if (count < 3000) {
seatTicket = count;
} else {
// 179
withoutSeatTicket = (count - 3000);
}
}
i = i + 10;
}
if (seatTicket > -1) {
ticketCountDesc = '本次列车您选择的席别尚有余票 ' + seatTicket + ' 张';
}
if (withoutSeatTicket > -1) {
ticketCountDesc += ' 无座 ' + withoutSeatTicket + ' 张';
}
return ticketCountDesc;
}
/* 以下为参考信息 */
/* ------------------------------------------- */
/**
* 余票查询中的预订链接
*
* 示例数据: 2013-02-02 北京→上海 D321
* <a name="btn130_2" class="btn130_2" style="text-decoration:none;" onclick="javascript:getSelected('D321#11:42#21:22#240000D32120#VNP#SHH#09:04#北京南#上海#01#04#O*****01644*****0244O*****3017#57463B183AA6FE5168F52051EF2411B00CBB7D60B8C691B50200094B#P2')">预订</a>
* @
see dynamic.12306.cn/otsweb/js/order/query_common_func.js?version=5.42
*/
function getSelected(selectStr) {
// 参数格式:#号分隔
var selectStr_arr = selectStr.split("#");
var station_train_code=selectStr_arr[0];
var lishi=selectStr_arr[1];
var starttime=selectStr_arr[2];
var trainno=selectStr_arr[3];
var from_station_telecode=selectStr_arr[4];
var to_station_telecode=selectStr_arr[5];
var arrive_time=selectStr_arr[6];
var from_station_name=selectStr_arr[7];
var to_station_name=selectStr_arr[8];
var from_station_no=selectStr_arr[9];
var to_station_no=selectStr_arr[10];
var ypInfoDetail=selectStr_arr[11];
var mmStr = selectStr_arr[12];
var locationCode = selectStr_arr[13];
// 参数值说明
// ----------
// 1. station_train_code // 车次(D321)
// 2. lishi // 历时(11:42)
// 3. starttime // 发车时间(21:22)
// 4. trainno // 列车ID(240000D32120), 可以从查询数据的table中获得该信息<span onmouseover="onStopHover('240000D32120#VNP#SHH')" id="id_240000D32120">D321</span>
// 5. from_station_telecode // 发站CODE(VNP)
// 6. to_station_telecode // 到站CODE(SHH)
// 7. arrive_time // 到站时间(09:04)
// 8. from_station_name // 发站名(北京南)
// 9. to_station_name // 到站名(上海)
// 10. from_station_no // 发站序号(该趟列车路线上的序号)(01)
// 11. to_station_no // 到站序号(该趟列车路线上的序号)(04)
// 12. ypInfoDetail // yp -> 余票(O*****01644*****0244O*****3017), 在预订页面left_ticket会补全星号O1234501644123450244O123453017, 可以认为这就代表票的ID, 具体含义请参考getTicketCountDesc
// 13. mmStr // token(57463B183AA6FE5168F52051EF2411B00CBB7D60B8C691B50200094B)
// 14. locationCode // TODO 随车次变化, 猜测是此趟车的到站CODE(P2)
var flag = true;
if (checkBeyondMixTicketNum()) {
flag = false;
return;
}
if (flag) {
submitRequest(station_train_code,lishi,starttime,trainno,from_station_telecode,to_station_telecode,arrive_time,from_station_name,to_station_name,from_station_no,to_station_no,ypInfoDetail,mmStr,locationCode);
}
}
/**
* 请求预订
*
* @
see dynamic.12306.cn/otsweb/js/order/query_common_bind.js?version=5.42
*/
function submitRequest(station_train_code,lishi,starttime,trainno,from_station_telecode,to_station_telecode,arrive_time,from_station_name,to_station_name,from_station_no,to_station_no,ypInfoDetail,mmStr,locationCode) {
$('#station_train_code').val(station_train_code);
$('#lishi').val(lishi);
$('#train_start_time').val(starttime);
$('#trainno').val(trainno);
$('#from_station_telecode').val(from_station_telecode);
$('#to_station_telecode').val(to_station_telecode);
$('#arrive_time').val(arrive_time);
$('#from_station_name').val(from_station_name);
$('#to_station_name').val(to_station_name);
$('#from_station_no').val(from_station_no);
$('#to_station_no').val(to_station_no);
$('#ypInfoDetail').val(ypInfoDetail);
$('#mmStr').val(mmStr);
$('#locationCode').val(locationCode);
// ctx = '/otsweb'
$('#orderForm').attr("action",
ctx+"/order/querySingleAction.do?method=submutOrderRequest");
$('#orderForm').submit();
}