V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ufologist
V2EX  ›  分享发现

获取12306余票信息

  •  
  •   ufologist · 2013-01-17 16:29:26 +08:00 · 5225 次点击
    这是一个创建于 4321 天前的主题,其中的信息可能已经有所发展或是发生改变。
    警告: 本程序是出于学习目的, 仅限于分析研究时用, 不可用于非法用途
    由于程序所造成的损失本人概不负责, 如有造成不便请通知本人删除程序

    欢迎大家去[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();
    }
    第 1 条附言  ·  2013-01-17 17:04:40 +08:00
    由于不清楚如何在v2ex中贴代码, 对丑陋的格局感到非常抱歉, 请大家移至gist fork
    第 2 条附言  ·  2013-01-17 17:15:18 +08:00
    试试直接贴上gist
    <script src="https://gist.github.com/4554460.js"></script>
    8 条回复    1970-01-01 08:00:00 +08:00
    tarsier
        1
    tarsier  
       2013-01-17 17:07:14 +08:00
    ms 可以直接嵌入gist ?
    ufologist
        2
    ufologist  
    OP
       2013-01-17 17:11:16 +08:00
    @tarsier 主题好像不能再编辑了吧? 不知具体如何华丽丽的插入gist
    tarsier
        3
    tarsier  
       2013-01-17 17:14:04 +08:00
    @ufologist 看看这个行不 http://www.v2ex.com/t/1244 我没试过
    ufologist
        4
    ufologist  
    OP
       2013-01-17 17:15:44 +08:00
    试试直接贴上gist
    <script src="https://gist.github.com/4554460.js"></script>
    unstop
        5
    unstop  
       2013-01-17 17:15:48 +08:00
    感谢楼主,楼主为了发这贴掉了不少血吧。

    楼下也给点一下感谢帮楼主回点血呗。
    ufologist
        6
    ufologist  
    OP
       2013-01-17 17:18:23 +08:00
    <script src="http://gist.github.com/4554460.js"></script>
    ufologist
        7
    ufologist  
    OP
       2013-01-17 17:20:04 +08:00
    ufologist
        8
    ufologist  
    OP
       2013-01-17 17:22:29 +08:00
    郁闷了, 如何删掉自己的回复, gist贴出来严重影响页面美观啊...求助@Livid
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2693 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:44 · PVG 19:44 · LAX 03:44 · JFK 06:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.