• 马后炮之12306抢票工具(四)--抢票Demo,2014年1月9日终结版


    时隔一年多,终于朋友的忽悠下吧抢票Demo的最后一步完善了,与2014年1月9日成功生成车票。

    Demo仅经过自己测试,并未在高峰期进行测试,代码质量很差,因为赶工,套用去年模板并未使用设计模式。

    代码存在如下BUG:

    1)代码使用 。net 4.5的事件,如果使用4.0或以下的同学,请根据错误提示,更改事件即可。已上传两个版(.net4.0 .net4.5)本。

    2)添加、刷新常用联系人功能缺失,按钮已屏蔽。请在官网添加后,重新登录软件即可刷新。

    3)验证码为手动输入,不支持自动识别。未做原因如下:1.本人太懒了,2.验证码经常变化,防止哪天变成公式计算,中文识别等特殊情况。

          时间仓促,代码整体结构是去年的,编写的代码很垃圾,未使用任何设计模式,仅从目的出发,并未考虑任何效率、兼容性、安全性、可维护性等问题。高手请绕道,勿喷,谢谢。

          如过有任何问题,可以在评论中一起探讨。如对代码有问题,可以一起讨论。

    本文最后放出的Demo仅供学习,请勿用于抢票操作。

    什么都不说,先上图:

    软件工作流程:

    1)拉取登陆验证码

    2)登陆,获取Cookie

    3)拉取常用联系人

    4)搜索车次前拉取城市地址,供给2221个城市

    5)按时间获取车次信息,并供给用户选择

    6)用户选择指定车次,指定日期获取车次及车票信息

    7)根据用户选择座位号,比多刚拉取的车票信息。如果没有车票则间隔6秒时间后重新刷票(int m = 6 * 100;)。

    8)如果有票,判断用户是否有勾选常用联系人,如果未勾选则不进行抢票

    9)抢票第一步:请求https://kyfw.12306.cn/otn/confirmPassenger/autoSubmitOrderReques页面获取Token

      提交车次信息: 

      Dictionary<string, string> dic = new Dictionary<string, string>();
      dic.Add("secretStr", train.Id);
      dic.Add("train_date", date);
      dic.Add("tour_flag", "dc");
      dic.Add("purpose_codes", "ADULT");
      dic.Add("query_from_station_name", From.Name);
      dic.Add("query_to_station_name", To.Name);
      dic.Add("", "");
      dic.Add("cancel_flag", "2");
      dic.Add("bed_level_order_num", "000000000000000000000000000000");
      dic.Add("passengerTicketStr", passengerTicketStr.ToString().TrimEnd('_'));
      dic.Add("oldPassengerStr", oldPassengerStr.ToString());

      Referer: "https://kyfw.12306.cn/otn/leftTicket/init"

       headers: new Dictionary<string, string>() { { "Origin", "https://kyfw.12306.cn" },{"X-Requested-With", "XMLHttpRequest"} }

       PostData、Cookie、Referer、Headers这几个是重点,必须要有,否则失效。

      返回Json:data.data.result中保存Token,如:

        Q6#BA6C4F23E49E84F96A07B8ECA37A9FF350DAD2E2F484AD96F61C2046#O007450669M0099501499019950025#1

      为统一名称,规定data.data.result使用#进行切割后命名:Q#长Token#短Token#数字

    10)抢票第二步:请求页面https://kyfw.12306.cn/otn/confirmPassenger/getQueueCountAsync获取车票数量

      提交车次数据:

      dic.Clear();
      dic.Add("train_date",
      (Convert.ToDateTime(date).ToString("ddd MMM dd yyy ", DateTimeFormatInfo.InvariantInfo) +
      DateTime.Now.ToString("HH:mm:ss").Replace(":", "%3A") + " GMT%2B0800 (China Standard Time)").Replace(' ', '+'));
      dic.Add("train_no", train.TrainNo);
      dic.Add("stationTrainCode", train.StationTrainCode);
      dic.Add("seatType", seatType);
      dic.Add("fromStationTelecode", train.from_station_telecode);
      dic.Add("toStationTelecode", train.end_station_telecode);
      dic.Add("leftTicket", token.ShortToken);
      dic.Add("purpose_codes", "ADULT");
      dic.Add("_json_att", "");

    //注:train_date可以使用URl编码即可,转码前内容:Fri Oct 10 2014 09:59:42 GMT+0800  (China Standard Time)

      Referer: "https://kyfw.12306.cn/otn/leftTicket/init"  

      headers:
      new Dictionary<string, string>()
      {
        {"Origin", "https://kyfw.12306.cn"},
        {"X-Requested-With", "XMLHttpRequest"}
      });

      返回值:data.data.ticket与短Token一致

    11)抢票第三步:https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew.do?module=login&rand=sjrand&拉取抢票验证码:

      Get页面,仍然要带入Cookies、Referer,但无需带入headers

    12)抢票第四步:请求https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueueAsys,生成车票

      请求数据:    

      dic.Clear();
      dic.Add("passengerTicketStr", System.Web.HttpUtility.UrlEncode((passengerTicketStr.ToString().TrimEnd('_'))).ToUpper());
      dic.Add("oldPassengerStr", System.Web.HttpUtility.UrlEncode(oldPassengerStr.ToString()).ToUpper());
      dic.Add("randCode", Code);
      dic.Add("purpose_codes", "ADULT");
      dic.Add("key_check_isChange", token.LongToken);
      dic.Add("leftTicketStr", token.ShortToken);
      dic.Add("train_location", token.Q);
      dic.Add("_json_att", "");

      Referer: "https://kyfw.12306.cn/otn/leftTicket/init"  

      headers:
      new Dictionary<string, string>()
      {
        {"Origin", "https://kyfw.12306.cn"},
        {"X-Requested-With", "XMLHttpRequest"}
      });

      注:passengerTicketStr、oldPassengerStr均要UrlEncode

     当data.data.submitStatus返回True时,恭喜你,已经抢票成功了,等待出票。

    总结思路:

    抢票与官方提供的页面自动提交抢票一次,但由于省去验证提交的验证码是否正确环节,固加快抢票速度。

     扩展思路:

    可以使用将抢票端分离,部署至多台计算机上,并且开启多线程。

    验证码统一传输至服务器端。

    再有验证码客户端去服务端拉取验证码后,由人工输入结果并返回。

    可以加快抢票速度。

    Demo .Net4.5 下载

    Demo .New4.0 下载

    Demo仅供学习,请勿用于抢票操作。

     很遗憾,由于部分原因,停止提供Demo的下载,十分抱歉。

  • 相关阅读:
    粘包_Server
    初见UDP_Server
    初见UDP_Client
    TCP/UDP协议
    网络编程相关概念
    mmap实现大文件快速拷贝
    生成这消费者问题(多线程实现)
    线程同步互斥实现资源访问
    信号灯(线程互斥)
    线程属性
  • 原文地址:https://www.cnblogs.com/comsokey/p/Train1230642014.html
Copyright © 2020-2023  润新知