当前位置:   article > 正文

从零实现一款12306抢票软件(三)_12306抢票java

12306抢票java

本文接上一篇《从零实现一款12306抢票软件(二)》。

其他接口就不一一介绍了,所有的原理都是一样的,作者可以自行探索。当然,我已经将所有的接口都探索完了,并实现了,我这里贴一下吧:

  1. /**
  2. *@desc: 封装获取验证码、校验验证码、登录等12306各个请求的类,Client12306.h文件
  3. *@author: zhangyl
  4. *@date: 2017.01.17
  5. */
  6. #ifndef __CLIENT_12306_H__
  7. #define __CLIENT_12306_H__
  8. #include <vector>
  9. #include <string>
  10. using namespace std;
  11. //车次类型
  12. #define TRAIN_GC 0x00000001
  13. #define TRAIN_D (0x00000001 << 1)
  14. #define TRAIN_Z (0x00000001 << 2)
  15. #define TRAIN_T (0x00000001 << 3)
  16. #define TRAIN_K (0x00000001 << 4)
  17. #define TRAIN_OTHER (0x00000001 << 5)
  18. #define TRAIN_ALL (TRAIN_GC | TRAIN_D | TRAIN_Z | TRAIN_T | TRAIN_K | TRAIN_OTHER)
  19. //票信息
  20. struct queryLeftNewDTO
  21. {
  22. string train_no;
  23. string station_train_code;
  24. string start_station_telecode; //始发站
  25. string start_station_name;
  26. string end_station_telecode; //终点站
  27. string end_station_name;
  28. string from_station_telecode; //出发站
  29. string from_station_name; //到达站
  30. string to_station_telecode;
  31. string to_station_name;
  32. string start_time;
  33. string arrive_time;
  34. string day_difference;
  35. string train_class_name;
  36. string lishi;
  37. string canWebBuy;
  38. string lishiValue;
  39. string yp_info;
  40. string control_train_day;
  41. string start_train_date;
  42. string seat_feature;
  43. string yp_ex;
  44. string train_seat_feature;
  45. string seat_types;
  46. string location_code;
  47. string from_station_no;
  48. string to_station_no;
  49. string control_day;
  50. string sale_time;
  51. string is_support_card;
  52. string controlled_train_flag;
  53. string controlled_train_message;
  54. string train_type_code;
  55. string start_province_code;
  56. string start_city_code;
  57. string end_province_code;
  58. string end_city_code;
  59. string swz_num; //商务座
  60. string rz_num; //软座
  61. string yz_num; //硬座
  62. string gr_num; //高级软卧
  63. string rw_num; //软卧
  64. string yw_num; //硬卧
  65. string tz_num; //特等座
  66. string zy_num; //一等座
  67. string ze_num; //二等座
  68. string wz_num; //无座
  69. string gg_num;
  70. string yb_num;
  71. string qt_num;
  72. };
  73. struct ticketinfo
  74. {
  75. queryLeftNewDTO DTO;
  76. string secretStr;
  77. string buttonTextInfo;
  78. };
  79. //var station_names = '@bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1@bji|北京|BJP|beijing|bj|2
  80. struct stationinfo
  81. {
  82. string code1;
  83. string hanzi;
  84. string code2;
  85. string pingyin;
  86. string simplepingyin;
  87. int no;
  88. };
  89. struct passenager
  90. {
  91. string code; //"8"
  92. string passenger_name; //"范蠡"
  93. string sex_code;// "M"
  94. string sex_name; // "男"
  95. string born_date; //"1989-12-08 00:00:00"
  96. string country_code;// "CN"
  97. string passenger_id_type_code;// "1"
  98. string passenger_id_type_name; // "二代身份证"
  99. string passenger_id_no; // "14292919781105815X"
  100. string passenger_type; // "1"
  101. string passenger_flag; // "0"
  102. string passenger_type_name; // "成人"
  103. string mobile_no; // "13917043320"
  104. string phone_no;
  105. string email; // "balloonxxx@qq.com"
  106. string address; // ""
  107. string postalcode; // ""
  108. string first_letter;// ""
  109. string recordCount;// "13"
  110. string total_times;// "99"
  111. string index_id;// "0"
  112. };
  113. class Client12306
  114. {
  115. public:
  116. static Client12306& GetInstance();
  117. private:
  118. Client12306();
  119. ~Client12306();
  120. private:
  121. Client12306(const Client12306&);
  122. Client12306& operator=(const Client12306&);
  123. public:
  124. bool ReloadVCodeImage();
  125. /**
  126. * 游客查票
  127. * https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-05-24&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=SHH&purpose_codes=ADULT
  128. * 应答:{“validateMessagesShowId”:”_validatorMessage”,”status”:true,”httpstatus”:200,”messages”:[],”validateMessages”:{}}
  129. *@param: train_date列车发车日期,格式:2017-01-28
  130. *@param: from_station出发站,格式:SHH 对应上海
  131. *@parma: to_station到站,格式:BJP 对应北京
  132. *@param: purpose_codes 票类型,成人票:ADULT 学生票:0X00
  133. *@param: v 查票结果
  134. */
  135. bool GuestQueryTicket(const char* train_date, const char* from_station, const char* to_station, const char* purpose_codes, vector<ticketinfo>& v);
  136. /**
  137. * 初始化session,获取JSESSIONID
  138. */
  139. bool loginInit();
  140. bool DownloadVCodeImage(const char* module = "login");
  141. /**
  142. *@return 0校验成功;1校验失败;2校验出错
  143. */
  144. int checkRandCodeAnsyn(const char* vcode);
  145. /**
  146. *@return 0校验成功;1校验失败;2校验出错
  147. */
  148. int loginAysnSuggest(const char* user, const char* pass, const char* vcode);
  149. /**
  150. * 正式登录
  151. */
  152. bool userLogin();
  153. /**
  154. * 模拟12306跳转
  155. */
  156. bool initMy12306();
  157. /**
  158. * 拉取乘客买票验证码
  159. */
  160. //bool GetVCodeImage();
  161. /**
  162. * 拉取乘客买票验证码
  163. */
  164. /**
  165. * 查询余票第一步
  166. * https://kyfw.12306.cn/otn/leftTicket/log?leftTicketDTO.train_date=2017-02-08&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=NJH&purpose_codes=ADULT
  167. * 应答:{“validateMessagesShowId”:”_validatorMessage”,”status”:true,”httpstatus”:200,”messages”:[],”validateMessages”:{}}
  168. *@param: train_date列车发车日期,格式:2017-01-28
  169. *@param: from_station出发站,格式:SHH 对应上海
  170. *@parma: to_station到站,格式:BJP 对应北京
  171. *@param: purpose_codes 票类型,成人票:ADULT 学生票:0X00
  172. */
  173. bool QueryTickets1(const char* train_date, const char* from_station, const char* to_station, const char* purpose_codes);
  174. /**
  175. * 查询余票第二步
  176. * 这几种情形都有可能,所以应该都尝试一下
  177. * https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2017-02-08&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=NJH&purpose_codes=ADULT
  178. * https://kyfw.12306.cn/otn/leftTicket/queryX?leftTicketDTO.train_date=2017-02-08&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=NJH&purpose_codes=ADULT
  179. * https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-02-08&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=NJH&purpose_codes=ADULT
  180. * {"status":false,"c_url":"leftTicket/query","c_name":"CLeftTicketUrl"}
  181. * {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"messages":["非法请求"],"validateMessages":{}}
  182. * 应答中含有实际余票信息
  183. *@param: train_date列车发车日期,格式:2017-01-28
  184. *@param: from_station出发站,格式:SHH 对应上海
  185. *@parma: to_station到站,格式:BJP 对应北京
  186. *@param: purpose_codes 票类型,成人票:ADULT 学生票:0X00
  187. */
  188. bool QueryTickets2(const char* train_date, const char* from_station, const char* to_station, const char* purpose_codes, vector<ticketinfo>& v);
  189. /**
  190. * 检测用户是否登录
  191. * https://kyfw.12306.cn/otn/login/checkUser POST _json_att=
  192. * Cookie: JSESSIONID=0A01D967FCD9827FC664E43DEE3C7C6EF950F677C2; __NRF=86A7CBA739653C1CC2C3C3AA7C88A1E3; BIGipServerotn=1742274826.64545.0000; BIGipServerportal=3134456074.17695.0000; current_captcha_type=Z; _jc_save_fromStation=%u4E0A%u6D77%2CSHH; _jc_save_toStation=%u5357%u4EAC%2CNJH; _jc_save_fromDate=2017-01-22; _jc_save_toDate=2017-01-22; _jc_save_wfdc_flag=dc
  193. * {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"flag":true},"messages":[],"validateMessages":{}}
  194. */
  195. bool checkUser();
  196. /**
  197. * 预提交订单 POST
  198. * https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest?secretStr=secretStr&train_date=2017-01-21&back_train_date=2016-12-23&tour_flag=dc&purpose_codes=ADULT&query_from_station_name=深圳&query_to_station_name=武汉&undefined=
  199. */
  200. bool submitOrderRequest(const char* secretStr, const char* train_date, const char* back_train_date, const char* tour_flag, const char* purpose_codes, const char* query_from_station_name, const char* query_to_station_name);
  201. /**
  202. * 模拟跳转页面InitDc,Post
  203. */
  204. bool initDc();
  205. /**
  206. * 拉取常用联系人 POST
  207. * https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs?_json_att=&REPEAT_SUBMIT_TOKEN=SubmitToken
  208. */
  209. bool getPassengerDTOs(vector<passenager>& v);
  210. /**
  211. * 购票人确定
  212. * https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo
  213. @param oldPassengerStr oldPassengerStr组成的格式:乘客名,passenger_id_type_code,passenger_id_no,passenger_type,’_
  214. 示例: 范蠡,1,14292919781105815X,1_
  215. @param passengerTicketStr passengerTicketStr组成的格式:seatType,0,票类型(成人票填1),乘客名,passenger_id_type_code,passenger_id_no,mobile_no,’N’
  216. 示例: O,0,1,范蠡,1,14292919781105815X,13817056720,N 101
  217. @tour_flag dc表示单程票
  218. 应答:{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"ifShowPassCode":"N","canChooseBeds":"N","canChooseSeats":"N","choose_Seats":"MOP9","isCanChooseMid":"N","ifShowPassCodeTime":"1","submitStatus":true,"smokeStr":""},"messages":[],"validateMessages":{}}
  219. */
  220. bool checkOrderInfo(const char* oldPassengerStr, const char* passengerTicketStr, const char* tour_flag, bool& bVerifyVCode);
  221. /**
  222. * 准备进入排队
  223. * https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount
  224. _json_att 10
  225. fromStationTelecode VNP 23
  226. leftTicket enu80ehMzuVJlK2Q43c6kn5%2BzQF41LEI6Nr14JuzThrooN57 63
  227. purpose_codes 00 16
  228. REPEAT_SUBMIT_TOKEN 691c09b5605e46bfb2ec2380ee65de0e 52
  229. seatType O 10
  230. stationTrainCode G5 19
  231. toStationTelecode AOH 21
  232. train_date Fri Feb 10 00:00:00 UTC+0800 2017 50
  233. train_location P2 17
  234. train_no 24000000G502 21
  235. 应答:{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"count":"4","ticket":"669","op_2":"false","countT":"0","op_1":"true"},"messages":[],"validateMessages":{}}
  236. */
  237. bool getQueueCount(const char* fromStationTelecode, const char* leftTicket, const char* purpose_codes, const char* seatType, const char* stationTrainCode, const char* toStationTelecode, const char* train_date, const char* train_location, const char* train_no);
  238. /**
  239. * 确认购买
  240. * https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue
  241. _json_att 10
  242. choose_seats 13
  243. dwAll N 7
  244. key_check_isChange 7503FD317E01E290C3D95CAA1D26DD8CFA9470C3643BA9799D3FB753 75
  245. leftTicketStr enu80ehMzuVJlK2Q43c6kn5%2BzQF41LEI6Nr14JuzThrooN57 66
  246. oldPassengerStr 范蠡,1,14292919781105815X,1_ 73
  247. passengerTicketStr O,0,1,范蠡,1,14292919781105815X
  248. ,13917043320,N 101
  249. purpose_codes 00 16
  250. randCode 9
  251. REPEAT_SUBMIT_TOKEN 691c09b5605e46bfb2ec2380ee65de0e 52
  252. roomType 00 11
  253. seatDetailType 000 18
  254. train_location P2 17
  255. 应答:{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"submitStatus":true},"messages":[],"validateMessages":{}}
  256. */
  257. bool confirmSingleForQueue(const char* leftTicketStr, const char* oldPassengerStr, const char* passengerTicketStr, const char* purpose_codes, const char* train_location);
  258. /**
  259. * 查询订单状态: https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random=1486368851278&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN=691c09b5605e46bfb2ec2380ee65de0e
  260. GET
  261. _json_att
  262. random 1486368851278
  263. REPEAT_SUBMIT_TOKEN 691c09b5605e46bfb2ec2380ee65de0e
  264. tourFlag dc
  265. 响应:{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"queryOrderWaitTimeStatus":true,"count":0,"waitTime":-1,"requestId":6234282826330508533,"waitCount":0,"tourFlag":"dc","orderId":"E061149209"},"messages":[],"validateMessages":{}}
  266. */
  267. bool queryOrderWaitTime(const char* tourflag, string& orderId);
  268. /**
  269. * https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue POST
  270. _json_att 10
  271. orderSequence_no E061149209 27
  272. REPEAT_SUBMIT_TOKEN 691c09b5605e46bfb2ec2380ee65de0e 52
  273. {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"submitStatus":true},"messages":[],"validateMessages":{}}
  274. */
  275. //bool resultOrderForDcQueue();
  276. /**
  277. * 未完成的订单页面 https://kyfw.12306.cn/otn/queryOrder/initNoComplete GET
  278. * 获取未完成的订单 https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete POST _json_att=
  279. */
  280. /*
  281. {
  282. "validateMessagesShowId": "_validatorMessage",
  283. "status": true,
  284. "httpstatus": 200,
  285. "data": {
  286. "orderDBList": [
  287. {
  288. "sequence_no": "E079331507",
  289. "order_date": "2017-02-09 10:10:55",
  290. "ticket_totalnum": 1,
  291. "ticket_price_all": 55300,
  292. "cancel_flag": "Y",
  293. "resign_flag": "4",
  294. "return_flag": "N",
  295. "print_eticket_flag": "N",
  296. "pay_flag": "Y",
  297. "pay_resign_flag": "N",
  298. "confirm_flag": "N",
  299. "tickets": [
  300. {
  301. "stationTrainDTO": {
  302. "trainDTO": {},
  303. "station_train_code": "G41",
  304. "from_station_telecode": "VNP",
  305. "from_station_name": "北京南",
  306. "start_time": "1970-01-01 09:16:00",
  307. "to_station_telecode": "AOH",
  308. "to_station_name": "上海虹桥",
  309. "arrive_time": "1970-01-01 14:48:00",
  310. "distance": "1318"
  311. },
  312. "passengerDTO": {
  313. "passenger_name": "范蠡",
  314. "passenger_id_type_code": "1",
  315. "passenger_id_type_name": "二代身份证",
  316. "passenger_id_no": "14262319781108815X",
  317. "total_times": "98"
  318. },
  319. "ticket_no": "E079331507110008B",
  320. "sequence_no": "E079331507",
  321. "batch_no": "1",
  322. "train_date": "2017-02-11 00:00:00",
  323. "coach_no": "10",
  324. "coach_name": "10",
  325. "seat_no": "008B",
  326. "seat_name": "08B号",
  327. "seat_flag": "0",
  328. "seat_type_code": "O",
  329. "seat_type_name": "二等座",
  330. "ticket_type_code": "1",
  331. "ticket_type_name": "成人票",
  332. "reserve_time": "2017-02-09 10:10:55",
  333. "limit_time": "2017-02-09 10:10:55",
  334. "lose_time": "2017-02-09 10:40:55",
  335. "pay_limit_time": "2017-02-09 10:40:55",
  336. "ticket_price": 55300,
  337. "print_eticket_flag": "N",
  338. "resign_flag": "4",
  339. "return_flag": "N",
  340. "confirm_flag": "N",
  341. "pay_mode_code": "Y",
  342. "ticket_status_code": "i",
  343. "ticket_status_name": "待支付",
  344. "cancel_flag": "Y",
  345. "amount_char": 0,
  346. "trade_mode": "",
  347. "start_train_date_page": "2017-02-11 09:16",
  348. "str_ticket_price_page": "553.0",
  349. "come_go_traveller_ticket_page": "N",
  350. "return_deliver_flag": "N",
  351. "deliver_fee_char": "",
  352. "is_need_alert_flag": false,
  353. "is_deliver": "N",
  354. "dynamicProp": "",
  355. "fee_char": "",
  356. "insure_query_no": ""
  357. }
  358. ],
  359. "reserve_flag_query": "p",
  360. "if_show_resigning_info": "N",
  361. "recordCount": "1",
  362. "isNeedSendMailAndMsg": "N",
  363. "array_passser_name_page": [
  364. "范蠡"
  365. ],
  366. "from_station_name_page": [
  367. "北京南"
  368. ],
  369. "to_station_name_page": [
  370. "上海虹桥"
  371. ],
  372. "start_train_date_page": "2017-02-11 09:16",
  373. "start_time_page": "09:16",
  374. "arrive_time_page": "14:48",
  375. "train_code_page": "G41",
  376. "ticket_total_price_page": "553.0",
  377. "come_go_traveller_order_page": "N",
  378. "canOffLinePay": "N",
  379. "if_deliver": "N",
  380. "insure_query_no": ""
  381. }
  382. ],
  383. "to_page": "db"
  384. },
  385. "messages": [],
  386. "validateMessages": {}
  387. }
  388. */
  389. /**
  390. * 已完成订单(改/退) : https://kyfw.12306.cn/otn/queryOrder/queryMyOrder POST
  391. * queryType 1 按订票日期 2 按乘车日期
  392. * 查询日期queryStartDate=2017-02-09&queryEndDate=2017-02-09
  393. * come_from_flag: my_order 全部 my_resign 可改签 my_cs_resign 可变更到站 my_refund 可退票
  394. * &pageSize=8&pageIndex=0&
  395. * query_where G 未出行订单 H 历史订单
  396. * sequeue_train_name 订单号/车次/乘客姓名
  397. */
  398. /* 历史订单格式
  399. 参见[历史订单.txt]
  400. */
  401. /**
  402. * 获取全国车站信息
  403. *@param si 返回的车站信息
  404. *@param bForceDownload 强制从网络上下载,即不使用本地副本
  405. */
  406. bool GetStationInfo(vector<stationinfo>& si, bool bForceDownload = false);
  407. /**
  408. * 获取所有高校信息 https://kyfw.12306.cn/otn/userCommon/schoolNames POST provinceCode=11&_json_att=
  409. */
  410. /**
  411. * 获取所有城市信息 https://kyfw.12306.cn/otn/userCommon/allCitys POST station_name=&_json_att=
  412. */
  413. /**
  414. * 查询常用联系人
  415. */
  416. bool QueryPassengers(int pageindex = 2, int pagesize = 10);
  417. bool GetVCodeFileName(char* pszDst, int nLength);
  418. private:
  419. bool GetCookies(const string& data);
  420. /**
  421. * 发送一个http请求
  422. *@param url 请求的url
  423. *@param strResponse http响应结果
  424. *@param get true为GET,false为POST
  425. *@param headers 附带发送的http头信息
  426. *@param postdata post附带的数据
  427. *@param bReserveHeaders http响应结果是否保留头部信息
  428. *@param timeout http请求超时时间
  429. */
  430. bool HttpRequest(const char* url, string& strResponse, bool get = true, const char* headers = NULL, const char* postdata = NULL, bool bReserveHeaders = false, int timeout = 10);
  431. private:
  432. char m_szCurrVCodeName[256]; //当前验证码图片的名称
  433. string m_strCookies;
  434. string m_strGlobalRepeatSubmitToken;
  435. string m_strKeyCheckIsChange;
  436. };
  437. #endif //!__CLIENT_12306_H__

具体的实现代码就不在文章中贴出来了,您可以下载我的代码。下载地址在微信公众号『easyserverdev』中回复『12306源码』即可得到下载地址,当然,由于12306的接口经常发生改变,当你拿到代码时,可能12306服务器的接口已经稍微发生了改变,您可以按上面介绍的原理做响应的修改。

最后当您实现了基本的登录和购票功能后,你就可以不断模拟某些请求去进行刷票了。

文章版权所有,转载请保留版权申明。

欢迎关注公众号『easyserverdev』。如果有任何技术或者职业方面的问题需要我提供帮助,可通过这个公众号与我取得联系,此公众号不仅分享高性能服务器开发经验和故事,同时也免费为广大技术朋友提供技术答疑和职业解惑,您有任何问题都可以在微信公众号直接留言,我会尽快回复您。

http://weixin.qq.com/r/DS_qsp3Em8DkrdnR93of (二维码自动识别)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/632100
推荐阅读
相关标签
  

闽ICP备14008679号