欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

实用攻略:12306抢票神器(二)——联系人设置与车次查询技巧

最编程 2024-02-23 10:58:59
...

马后炮之12306抢票工具(一) -- 登录

今天完成模块:

添加常用联系人

获取车站列表

获取车次信息

获取常用联系人已经在马后炮之12306抢票工具(一) -- 登录中介绍,不在重复

 

遇到问题:

1)用TextBox输出日志时,系统UI卡死

解决多线程UI输入日志问题
 1         private void ShowMessage(string message, bool isNewLine = true)
 2         {
 3             this.Invoke(new Action<string, bool>((m, n) => { _ShowMessage(m, n); }), message, isNewLine);
 4       
 5         }   
 6         private void _ShowMessage(string message, bool isNewLine = true)
 7         {
 8             richTextBox1.AppendText(message);
 9             if (isNewLine)
10             {
11                 richTextBox1.AppendText("\r\n");
12             }
13         }

2)TextBox焦点一直在底部

保持焦点一直在底部
1             richTextBox1.SelectionStart = richTextBox1.TextLength;
2             richTextBox1.ScrollToCaret();

3)checkedListBox使用DataSource属性绑定数据源(自定义类列表)后,显示绑定类型。

该问题未解决。如果知道的朋友,请提供以下代码,谢谢。

 

 

      重写ToString方法。 

public override string ToString()
        {
            return string.Format("{0} {1}({3})->{2}({4})", TrainValue, StartStation, EndStation, StartTime, EndTime);
        }

 

 添加常用联系人:

添加常用联系人分两步:

第一步:访问https://dynamic.12306.cn/otsweb/passengerAction.do?method=initUsualPassenger12306# 获取Token

格式:<div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="5d920dbd8e3216dd0bd18eae5f96ccc9"></div>

第二步:将Token和其他数据Post到https://dynamic.12306.cn/otsweb/passengerAction.do?method=savePassenger 创建联系人

PS:没有使用购票时”添加至常用联系人“选项,而是使用”我的12306"页面中的常用联系人功能。

因为在秒杀应用中,浪费十几毫秒都可能导致抢不到,虽然抢票没有秒杀那么夸张,但是不排除因为购票时使用添加联系人功能,导致浪费几十毫秒,甚至几秒。

获取Token
 1          private const string UrlCreateFavoriteContact1_GetToken = "https://dynamic.12306.cn/otsweb/passengerAction.do?method=initUsualPassenger12306#";
 2 
 3  string token = "";
 4             string str;
 5             HttpWebResponse response;
 6 
 7             #region 第一步获取Token
 8             try
 9             {
10 
11                 response = HttpHelper.CreateGetHttpResponse(UrlCreateFavoriteContact1_GetToken, timeout, userAgent, cookie ?? Cookies, "");
12 
13                 cookies.Add(response.Cookies);
14 
15                 using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
16                 {
17                     str = reader.ReadToEnd();
18                 }
19             }
20             catch (Exception)
21             {
22                 return new CreateFavoriteContactResponse() { IsCreated = false, Message = "网络可能存在问题,请您重试一下!", type = ErrorType.NetworkError };
23             }
24 
25 
26             Regex Token = new Regex("<input type=\"hidden\" name=\"org.apache.struts.taglib.html.TOKEN\" value=\"(?<token>[^\"]*?)\"></div>");
27 
28             if (Token.IsMatch(str))
29             {
30                 token = Token.Matches(str)[0].Groups["token"].Value;
31             }
32 
33             #endregion
创建联系人
        private const string UrlCreateFavoriteContact2_Create = "https://dynamic.12306.cn/otsweb/passengerAction.do?method=savePassenger";

 Dictionary<string, string> dic = new Dictionary<string, string>();
            dic.Add("org.apache.struts.taglib.html.TOKEN", token);
            dic.Add("name", name);
            dic.Add("sex_code", sexCode);
            dic.Add("born_date", bornDate);
            dic.Add("country_code", "CN");
            dic.Add("card_type", cardType);
            dic.Add("card_no", cardNo);
            dic.Add("passenger_type", "1");//暂时只支持添加成人
            dic.Add("mobile_no", mobileNo);
            dic.Add("phone_no", "");
            dic.Add("email", "");
            dic.Add("address", "");
            dic.Add("postalcode", "");
            dic.Add("studentInfo.province_code", "11");
            dic.Add("studentInfo.school_code", "");
            dic.Add("studentInfo.school_name", "简码/汉字");
            dic.Add("studentInfo.department", "");
            dic.Add("studentInfo.school_class", "");
            dic.Add("studentInfo.student_no", "");
            dic.Add("studentInfo.school_system", "4");
            dic.Add("studentInfo.enter_year", "2002");
            dic.Add("studentInfo.preference_card_no", "");
            dic.Add("studentInfo.preference_from_station_name", "简码/汉字");
            dic.Add("studentInfo.preference_from_station_code", "");
            dic.Add("studentInfo.preference_to_station_name", "简码/汉字");
            dic.Add("studentInfo.preference_to_station_code", "");

            try
            {

                response = HttpHelper.CreatePostHttpResponse(UrlCreateFavoriteContact2_Create, dic, timeout, userAgent, Encoding.UTF8, cookie ?? Cookies, "https://dynamic.12306.cn/otsweb/passengerAction.do?method=initAddPassenger&");

                cookies.Add(response.Cookies);

                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                {
                    str = reader.ReadToEnd();
                }
            }
            catch (Exception)
            {
                return new CreateFavoriteContactResponse() { IsCreated = false, Message = "网络可能存在问题,请您重试一下!", type = ErrorType.NetworkError };
            }

            Regex message = new Regex("var message = \"(?<message>[^\"]*?)\";");

            if (message.IsMatch(str))
            {
                str = message.Matches(str)[0].Groups["message"].Value;
                if (str.Contains("添加常用联系人成功"))
                {
                    return new CreateFavoriteContactResponse() { IsCreated = true, Message = "", type = ErrorType.None };
                }
                else
                {
                    return new CreateFavoriteContactResponse() { IsCreated = false, Message = str, type = ErrorType.OtherError };
                }
            }

            return new CreateFavoriteContactResponse() { IsCreated = false, Message = "其他错误!", type = ErrorType.OtherError };

 

 获取车站列表:

访问https://dynamic.12306.cn/otsweb/js/common/station_name.js 获取车站列表(该页面可以匿名访问)

格式:var station_names
='@bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1@bji|北京|BJP|beijing|bj|2......@zzd|涿州东|ZAP|zhuozhoudong|zzd|2140@zzd|郑州东|ZAF|zhengzhoudong|zzd|2141';

获取车站列表
private const string UrlGetStations = "https://dynamic.12306.cn/otsweb/js/common/station_name.js";

  /// <summary>
        /// 获取车站信息
        /// </summary>
        /// <param name="timeout"></param>
        /// <param name="userAgent"></param>
        /// <param name="cookie"></param>
        public static List<Station> GetStations(int? timeout = null, string userAgent = null,
                                               CookieCollection cookie = null)
        {
            List<Station> list = new List<Station>();

            var response = HttpHelper.CreateGetHttpResponse(UrlGetStations, timeout, userAgent, cookie ?? Cookies);

            cookies.Add(response.Cookies);
            try
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                {
                    var str = reader.ReadToEnd();

                    Regex stationNamesRegex = new Regex("'(?<stationNames>[^\']*?)'");

                    if (stationNamesRegex.IsMatch(str))
                    {
                        string stationNames = stationNamesRegex.Matches(str)[0].Groups["stationNames"].Value;


                        string[] stations = stationNames.Split('@');

                        foreach (var station in stations)
                        {
                            if (string.IsNullOrEmpty(station))
                            {
                                continue;
                            }

                            string[] names = station.Split('|');

                            list.Add(new Station()
                            {
                                Shorthand = names[0],
                                Name = names[1],
                                Code = names[2],
                                Pinyin = names[3],
                                FirstLetter = names[4],
                                Order = names[5]
                            });
                        }
                    }
                }
            }
            catch (Exception)
            {

            }

            return list;
        }
实体类
  class Stations
    {
        static List<Station> list = new List<Station>();

        private static object obj = new object();

        public static List<Station> List
        {
            get
            {
                if (list.Count <= 0)
                {
                    lock (obj)
                    {
                        if (list.Count <= 0)
                        {
                            list = _12306Class.GetStations();
                        }
                    }
                }
                return list;
            }
        }
    }

    /// <summary>
    /// 站点信息
    /// </summary>
    class Station
    {
        /// <summary>
        /// 站点名
        /// </summary>
        public string Name;

        /// <summary>
        /// 
        /// </summary>
        public string Code;

        /// <summary>
        /// 首字母
        /// </summary>
        public string FirstLetter;

        /// <summary>
        /// 全拼
        /// </summary>
        public string Pinyin;

        /// <summary>
        /// 简写
        /// </summary>
        public string Shorthand;

        /// <summary>
        /// 排序
        /// </summary>
        public string Order;
    }

 

获取车次信息:

第一步:将车站名转换为车站Code

第二步:将内容发送到https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=queryststrainall 页面

PS:需要注意,在不同时间获取的车次不同,可能返回空

转换
   var startStation = Stations.List.SingleOrDefault(fun => fun.Name == textBox1.Text.Trim());
            if (startStation == null)
            {
                MessageBox.Show(string.Format("找不到站点:{0},请重新输入!", textBox1.Text.Trim()));
                return;
            }

            var endStation = Stations.List.SingleOrDefault(fun => fun.Name == textBox2.Text.Trim());

            if (endStation == null)
            {
                MessageBox.Show(string.Format("找不到站点:{0},请重新输入!", textBox2.Text.Trim()));

                return;
            }
获取车次信息
 1         private const string UrlGetTrains = "https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=queryststrainall";
 2 
 3    public static List<Train> GetTrains(string data, string fromstation, string tostation,
 4                                             int? timeout = null, string userAgent = null, CookieCollection cookie = null)
 5         {
 6             List<Train> list = new List<Train>();
 7             Dictionary<string, string> dic = new Dictionary<string, string>();
 8             dic.Add("date", data);
 9             dic.Add("fromstation", fromstation);
10             dic.Add("tostation", tostation);
11             dic.Add("starttime", "00:00--24:00");
12 
13             string str = "";
14 
15             try
16             {
17                 var response = HttpHelper.CreatePostHttpResponse(UrlGetTrains, dic, timeout, userAgent, Encoding.UTF8, cookie ?? Cookies, "https://dynamic.12306.cn/otsweb/passengerAction.do?method=initAddPassenger&");
18 
19                 cookies.Add(response.Cookies);
20 
21                 using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
22                 {
23                     str = reader.ReadToEnd();
24                 }
25             }
26             catch (Exception)
27             {
28                 return null;
29             }
30 
31             if (!string.IsNullOrEmpty(str))
32             {
33                 // 解析第一次返回值,获取登录随机验证码loginRand,执行登录
34                 var v = new IronJS.Hosting.CSharp.Context();
35                 string strJson = "var json = " + str;
36                 dynamic dy = v.Execute(strJson);
37 
38                 for (int i = 0; i < dy.length; i++)
39                 {
40                     list.Add(new Train()
41                         {
42                             Id = dy[i].id,
43                             EndStation = dy[i].end_station_name,
44                             EndTime = dy[i].end_time,
45                             StartStation = dy[i].start_station_name,
46                             StartTime = dy[i].start_time,
47                             TrainValue = dy[i].value
48                         });
49                 }
50             }
51 
52             return list;
53         }
实体类
class Trains
    {
        static List<Train> list = new List<Train>();

        public List<Train> List
        {
            get { return list; }
        }

        public static void AddTrains(List<Train> trains)
        {
            var v = trains.Where(fun => list.SingleOrDefault(m => m.Id == fun.Id) == null);

            if (v.Any())
            {
                list.AddRange(v);

                if (TrainsChanged != null)
                {
                    TrainsChanged(v, list);
                }
            }
        }

        public static event EventHandler<List<Train>> TrainsChanged;
    }

    public class Train
    {
        public string Id;
        public string StartStation;
        public string EndStation;
        public string StartTime;
        public string EndTime;
        public string TrainValue;

        public virtual string ToString()
        {
            return string.Format("{0} {1}({3})->{2}({4})", TrainValue, StartStation, EndStation, StartTime, EndTime);
        }
    }

 

报文:

添加常用联系人
POST /otsweb/passengerAction.do?method=savePassenger HTTP/1.0
Accept-Language: zh-CN,en-GB;q=0.5
Pragma: no-cache
Cache-Control: no-cache
X-Requested-With: XMLHttpRequest
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Content-Type: application/x-www-form-urlencoded
Referer: https://dynamic.12306.cn/otsweb/passengerAction.do?method=initAddPassenger&
User-Agent: Mozilla/6.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20120131 Firefox/14.0
Host: dynamic.12306.cn
Cookie: JSESSIONID=BE43978FDEF213DCB1659646FA17F82D; BIGipServerotsweb=2597585162.48160.0000
Content-Length: 691
Connection: Keep-Alive

org.apache.struts.taglib.html.TOKEN=a42a32e61f183cfef893d6d945426196&name=XX&sex_code=M&born_date=1990-01-01&country_code=CN&card_type=2&card_no=1234567890123456789&passenger_type=1&mobile_no=15814000000&phone_no=&email=&address=&postalcode=&studentInfo.province_code=11&studentInfo.school_code=&studentInfo.school_name=简码/汉字&studentInfo.department=&studentInfo.school_class=&studentInfo.student_no=&studentInfo.school_system=4&studentInfo.enter_year=2002&studentInfo.preference_card_no=&studentInfo.preference_from_station_name=简码/汉字&studentInfo.preference_from_station_code=&studentInfo.preference_to_station_name=简码/汉字&studentInfo.preference_to_station_code=
获取车站信息
GET /otsweb/js/common/station_name.js HTTP/1.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/6.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20120131 Firefox/14.0
Host: dynamic.12306.cn
Cookie: JSESSIONID=BE43978FDEF213DCB1659646FA17F82D; BIGipServerotsweb=2597585162.48160.0000
Connection: Keep-Alive

---------------------------------------------------------------------------------


var station_names ='@bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1@bji|北京|BJP|beijing|bj|2@bjn|北京南|VNP|beijingnan|bjn|3@bjx|北京西|BXP|beijingxi|bjx|4@cqb|重庆北|CUW|chongqingbei|cqb|5@cqi|重庆|CQW|chongqing|cq|6@cqn|重庆南|CRW|chongqingnan|cqn|7@sha|上海|SHH|shanghai|sh|8@shn|上海南|SNH|shanghainan|shn|9@shq|上海虹桥|AOH|shanghaihongqiao|shhq|10@shx|上海西|SXH|shanghaixi|shx|11@tjb|天津北|TBP|tianjinbei|tjb|12@tji|天津|TJP|tianjin|tj|13@tjn|天津南|TIP|tianjinnan|tjn|14@tjx|天津西|TXP|tianjinxi|tjx|15@cch|长春|CCT|changchun|cc|16@ccn|长春南|CET|changchunnan|ccn|17@ccx|长春西|CRT|changchunxi|ccx|18@cdd|成都东|ICW|chengdudong|cdd|19@cdn|成都南|CNW|chengdunan|cdn|20@cdu|成都|CDW|chengdu|cd|21@csh|长沙|CSQ|changsha|cs|22@csn|长沙南|CWQ|changshanan|csn|23@fzh|福州|FZS|fuzhou|fz|24@fzn|福州南|FYS|fuzhounan|fzn|25@gya|贵阳|GIW|guiyang|gy|26@gzb|广州北|GBQ|guangzhoubei|gzb|27@gzd|广州东|GGQ|guangzhoudong|gzd|28@gzh|广州|GZQ|guangzhou|gz|29@gzn|广州南|IZQ|guangzhounan|gzn|30@gzx|广州西|GXQ|guangzhouxi|gzx|31@heb|哈尔滨|HBB|haerbin|heb|32@hed|哈尔滨东|VBB|harbindong|hebd|33@hex|哈尔滨西|VAB|haerbinxi|hebx|34@hfe|合肥|HFH|hefei|hf|35@hfx|合肥西|HTH|hefeixi|hfx|36@hhd|呼和浩特东|NDC|huhehaotedong|hhhtd|37@hht|呼和浩特|HHC|hohhot|hhht|38@hkd|海口东|HMQ|haikoudong|hkd|39@hko|海口|VUQ|haikou|hk|40@hzh|杭州|HZH|hangzhou|hz|41@hzn|杭州南|XHH|hangzhounan|hzn|42@jna|济南|JNK|jinan|jn|43@jnd|济南东|JAK|jinandong|jnd|44@jnx|济南西|JGK|jinanxi|jnx|45@kmi|昆明|KMM|kunming|km|46@kmx|昆明西|KXM|kunmingxi|kmx|47@lsa|拉萨|LSO|lasa|ls|48@lzd|兰州东|LVJ|lanzhoudong|lzd|49@lzh|兰州|LZJ|lanzhou|lz|50@lzx|兰州西|LAJ|lanzhouxi|lzx|51@nch|南昌|NCG|nanchang|nc|52@nji|南京|NJH|nanjing|nj|53@njn|南京南|NKH|nanjingnan|njn|54@nni|南宁|NNZ|nanning|nn|55@sjb|石家庄北|VVP|shijiazhuangbei|sjzb|56@sjz|石家庄|SJP|shijiazhuang|sjz|57@sya|沈阳|SYT|shenyang|sy|58@syb|沈阳北|SBT|shenyangbei|syb|59@syd|沈阳东|SDT|shenyangdong|syd|60@tyb|太原北|TBV|taiyuanbei|tyb|61@tyd|太原东|TDV|taiyuandong|tyd|62@tyu|太原|TYV|taiyuan|ty|63@wha|武汉|WHN|wuhan|wh|64@wjx|王家营西|KNM|wangjiayingxi|wjyx|65@wlq|乌鲁木齐|WMR|wulumuqi|wlmq|66@xab|西安北|EAY|xianbei|xab|67@xan|西安|XAY|xian|xa|68@xan|西安南|CAY|xiannan|xan|69@xnx|西宁西|XXO|xiningxi|xnx|70@ych|银川|YIJ|yinchuan|yc|71@zzh|郑州|ZZF|zhengzhou|zz|72@aes|阿尔山|ART|aershan|aes|73@aka|安康|AKY|ankang|ak|74@aks|阿克苏|ASR|akesu|aks|75@alh|阿里河|AHX|alihe|alh|76@alk|阿拉山口|AKR|alashankou|alsk|77@api|安平|APT|anping|ap|78@aqi|安庆|AQH|anqing|aq|79@ash|安顺|ASW|anshun|as|80@ash|鞍山|AST|anshan|as|81@aya|安阳|AYF|anyang|ay|82@ban|北安|BAB|beian|ba|83@bbu|蚌埠|BBH|bengbu|bb|84@bch|白城|BCT|baicheng|bc|85@bha|北海|BHZ|beihai|bh|86@bhe|白河|BEL|baihe|bh|87@bji|白涧|BAP|baijian|bj|88@bji|宝鸡|BJY|baoji|bj|89@bji|滨江|BJB|binjiang|bj|90@bkt|博克图|BKX|bugt|bkt|91@bse|百色|BIZ|baise|bs|92@bss|白山市|HJL|baishanshi|bss|93@bta|北台|BTT|beitai|bt|94@btd|包头东|BDC|baotoudong|btd|95@bto|包头|BTC|baotou|bt|96@bts|北屯市|BXR|beitunshi|bts|97@bxi|本溪|BXT|benxi|bx|98@byb|白云鄂博|BEC|bayanobo|byeb|99@byx|白银西|BXJ|baiyinxi|byx|100@bzh|亳州|BZH|bozhou|bz|101@cbi|赤壁|CBN|chibi|cb|102@cde|常德|VGQ|changde|cd|103@cde|承德|CDP|chengde|cd|104@cdi|长甸|CDT|changdian|cd|105@cfe|赤峰|CFD|chifeng|cf|106@cli|茶陵|CDG|chaling|cl|107@cna|苍南|CEH|cangnan|cn|108@cpi|昌平|CPP|changping|cp|109@cre|崇仁|CRG|chongren|cr|110@ctu|昌图|CTT|changtu|ct|111@ctz|长汀镇|CDB|changtingzhen|ctz|112@cxi|崇信|CIJ|chongxin|cx|113@cxi|曹县|CXK|caoxian|cx|114@cxi|楚雄|COM|chuxiong|cx|115@cxt|陈相屯|CXT|chenxiangtun|cxt|116@czb|长治北|CBF|changzhibei|czb|117@czh|长征|CZJ|changzheng|cz|118@czh|池州|IYH|chizhou|cz|119@czh|常州|CZH|changzhou|cz|120@czh|郴州|CZQ|chenzhou|cz|121@czh|长治|CZF|changzhi|cz|122@czh|沧州|COP|cangzhou|cz|123@czu|崇左|CZZ|chongzuo|cz|124@dab|大安北|RNT|daanbei|dab|125@dch|大成|DCT|dacheng|dc|126@ddo|丹东|DUT|dandong|dd|127@dfh|东方红|DFB|dongfanghong|dfh|128@dgd|东莞东|DMQ|dongguandong|dgd|129@dhs|