本文叙述的是使用C#调用12306的API做余票查询程序的方法。

先看一下程序运行截图。本程序使用WPF。

1. 了解12306API

登陆12306网站,点击余票查询,我们查询从北京到上海的火车票。

抓取到的数据包如下:

请求报文头:

这就是我们封装查询报文时需要模仿的格式。

返回报文为一个json格式的字符串,下面是一个样例:

{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"datas":[{"train_no":"240000T1090K","station_train_code":"T109","start_station_telecode":"BJP","start_station_name":"北京","end_station_telecode":"SHH","end_station_name":"上海","from_station_telecode":"BJP","from_station_name":"北京","to_station_telecode":"SHH","to_station_name":"上海","start_time":"19:33","arrive_time":"10:44","day_difference":"1","train_class_name":"","lishi":"15:11","canWebBuy":"Y","lishiValue":"911","yp_info":"10177531664047650000101775000060879500063030450000","control_train_day":"20201231","start_train_date":"20150110","seat_feature":"W343136333","yp_ex":"1040106030","train_seat_feature":"3","seat_types":"14163","location_code":"P4","from_station_no":"01","to_station_no":"11","control_day":59,"sale_time":"1000","is_support_card":"0","note":"","gg_num":"--","gr_num":"6","qt_num":"--","rw_num":"无","rz_num":"--","tz_num":"--","wz_num":"166","yb_num":"--","yw_num":"无","yz_num":"无","ze_num":"--","zy_num":"--","swz_num":"--"},{"train_no":"240000D3130B","station_train_code":"D313","start_station_telecode":"VNP","start_station_name":"北京南","end_station_telecode":"SHH","end_station_name":"上海","from_station_telecode":"VNP","from_station_name":"北京南","to_station_telecode":"SHH","to_station_name":"上海","start_time":"19:34","arrive_time":"07:27","day_difference":"1","train_class_name":"动车","lishi":"11:53","canWebBuy":"Y","lishiValue":"713","yp_info":"O030900114O0309030154061500346","control_train_day":"20301231","start_train_date":"20150110","seat_feature":"O343W3","yp_ex":"O0O040","train_seat_feature":"3","seat_types":"OO4","location_code":"P3","from_station_no":"01","to_station_no":"04","control_day":59,"sale_time":"1230","is_support_card":"0","note":"","gg_num":"--","gr_num":"--","qt_num":"--","rw_num":"346","rz_num":"--","tz_num":"--","wz_num":"15","yb_num":"--","yw_num":"--","yz_num":"--","ze_num":"114","zy_num":"--","swz_num":"--"},{"train_no":"240000D31102","station_train_code":"D311","start_station_telecode":"VNP","start_station_name":"北京南","end_station_telecode":"SHH","end_station_name":"上海","from_station_telecode":"VNP","from_station_name":"北京南","to_station_telecode":"SHH","to_station_name":"上海","start_time":"21:16","arrive_time":"08:58","day_difference":"1","train_class_name":"动车","lishi":"11:42","canWebBuy":"Y","lishiValue":"702","yp_info":"O030900158O0309030174061500296","control_train_day":"20301231","start_train_date":"20150110","seat_feature":"O343W3","yp_ex":"O0O040","train_seat_feature":"3","seat_types":"OO4","location_code":"P2","from_station_no":"01","to_station_no":"04","control_day":59,"sale_time":"1230","is_support_card":"0","note":"","gg_num":"--","gr_num":"--","qt_num":"--","rw_num":"296","rz_num":"--","tz_num":"--","wz_num":"17","yb_num":"--","yw_num":"--","yz_num":"--","ze_num":"158","zy_num":"--","swz_num":"--"},{"train_no":"240000D32109","station_train_code":"D321","start_station_telecode":"VNP","start_station_name":"北京南","end_station_telecode":"SHH","end_station_name":"上海","from_station_telecode":"VNP","from_station_name":"北京南","to_station_telecode":"SHH","to_station_name":"上海","start_time":"21:23","arrive_time":"09:12","day_difference":"1","train_class_name":"动车","lishi":"11:49","canWebBuy":"Y","lishiValue":"709","yp_info":"O030900210O0309030154061500236","control_train_day":"20301231","start_train_date":"20150110","seat_feature":"O343W3","yp_ex":"O0O040","train_seat_feature":"3","seat_types":"OO4","location_code":"P2","from_station_no":"01","to_station_no":"05","control_day":59,"sale_time":"1230","is_support_card":"0","note":"","gg_num":"--","gr_num":"--","qt_num":"--","rw_num":"236","rz_num":"--","tz_num":"--","wz_num":"15","yb_num":"--","yw_num":"--","yz_num":"--","ze_num":"210","zy_num":"--","swz_num":"--"}],"flag":true,"searchDate":"2015年01月10号  周六"},"messages":[],"validateMessages":{}}

在这个json串中包含了查询到的车辆余票信息,也包含查询者的信息。我们只需要提取其中有用的部分。现将其中有用的部分列举如下:


其中有一些字段没有标注释,目前意义未知

通过解析这个json串,就能完成余票查询的工作。

2. 具体操作方法

根据上面抓取到的数据包,我们知道API的地址为:

string uri = @"https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes={0}&queryDate={1}&from_station={2}&to_station={3}";
uri = string.Format(uri, purpose, date, from, to);

可以看出,其中一共有4个参数,perpose表示票的种类(成人票,学生票等),date表示查询火车开车的日期(格式为:yyyy-mm-dd),from表示出发车站代码,end表示到达车站代码。代码均为3位数大写英文字母,每一个代码唯一对应一个车站。

车站代码可以到下面链接处下载:

http://download.csdn.net/detail/xiahn1a/8348211

对于上面给出的链接中下载到的代码的处理方法:

文档中代码是如下格式:

bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1

车站间使用@分割,每条信息间使用|分割。我们所需要的只是第2项名称和第3项代码,其他的拼音,编号等不是我们所需要的内容。

根据代码文档我们可以建立一个站名到代码的映射关系。

给一个链接的例子,在2015年1月10日查询从北京到上海的成人票:

https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=2015-01-10&from_station=BJP&to_station=SHH

剩下的就是按照上面截图的格式封装报文即可,需要注意的是我们需要采用ssl,有一个验证证书的过程,还需要建立一个CookieContainer。

对于返回的json格式串,使用NewtonSoft.Json类中的相应函数将json字符串转换为jclass对象,然后可以直接通过Linq语句查询出所需要的对象。

相关的封装报文步骤代码如下:

private CookieContainer cc = new CookieContainer();public void GetInfo(string purpose, string date, string from, string to)
{try{string uri = @"https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes={0}&queryDate={1}&from_station={2}&to_station={3}";uri = string.Format(uri, purpose, date, from, to);ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);request.CookieContainer = cc;request.ProtocolVersion = HttpVersion.Version10;request.Accept = @"*/*";request.UserAgent = @"Mozilla/5.0 (Windows NT 6.4; WOW64; Trident/7.0; rv:11.0) like Gecko";request.Referer = @"https://kyfw.12306.cn/otn/lcxxcx/init";request.ContentType = @"application/x-www-form-urlencoded";request.Method = "GET";using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()){using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)){string res = reader.ReadToEnd();jclass jc1 = JsonConvert.DeserializeObject<jclass>(res);getData(jc1);}}}catch (Exception ex){MessageBox.Show(ex.Message);}return ;
}private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{return true; //总是接受
}

本文完成于2015.1.10,到目前为止,该API仍可用。

C#调用12306API做余票查询相关推荐

  1. 使用c#中的HttpWebRequest实现12306余票查询

    准备工作 下载用于解析JSON的类库(Newtonsoft.Json.dll)(下载地址:Newtonsoft.Json.dll): 在C#项目中添加对其的引用. 在程序中导入命名空间: 1 2 3 ...

  2. 快春运了,做个火车余票查询接口,余票来源12306,图是百度地图

    摘要:做个火车票查询余票接口,数据来源于12306,地图使用百度地图(未完成) 今天本来想查询一下回家的车票,结果坑爹的发现12306网站死活打不开,尼玛真实坑爹,想查询一下余票都怎么难 于是自己决定 ...

  3. 做个火车余票查询接口,余票来源12306,图是百度地图

    摘要:做个火车票查询余票接口,数据来源于12306,地图使用百度地图(未完成) 今天本来想查询一下回家的车票,结果坑爹的发现12306网站死活打不开,尼玛真实坑爹,想查询一下余票都怎么难 于是自己决定 ...

  4. 返乡之路不容易之12306余票查询并给出备选方案v2

    在第一版的返乡之路不容易之12306余票查询并给出备选方案中,给出了余票查询和备选方案推荐,但当时有两个问题: 没有备选排名:虽然给出了备选,但哪个备选好没有给出排序 没有座位信息(商务/一等/二等/ ...

  5. 12306 余票查询API浅探索

    12306 余票查询API浅探索 余票查询请求分析 响应数据解密代码查找调试 数据说明 余票查询请求分析 点击查询,F12进入控制台,进入NetWork面板,查看发送的请求: 点入请求查看详情,很明显 ...

  6. 铁路局12306余票查询的实现

    离上次写的类似于铁道部12306城市选择框的实现过了都快一个月了,最近一直在忙,在学习sharepoint2013,虽然早就实现了12306的余票查询,但是一直没抽出时间来写,刚好这几天也快放假了,抽 ...

  7. 12306之余票查询流程解析

    前言 本套教程共分3章: 12306之登录流程解析 12306之余票查询解析 12306之下单流程解析 本套内容主要用于分析12306购票流程,意在编写一套自动购票小程序.12306接口 api 经常 ...

  8. 12306火车余票查询

    测试地址:http://gengjian.24.lc/japson/123060.htm 调用12306官网的查询接口. 123060.htm 火车票余票查询Demo By Genng.<br& ...

  9. Python大法之从火车余票查询到打造抢Supreme神器

    本文作者:i春秋作家--阿甫哥哥 系列文章专辑:https://bbs.ichunqiu.com/forum.php?mod=collection&action=view&ctid=9 ...

最新文章

  1. 在NVIDIA A100 GPU中使用DALI和新的硬件JPEG解码器快速加载数据
  2. 奥比中光Gemini 3D双目结构光深度相机在Android平台上深度数据噪点非常多的问题
  3. (转)Response.Redirect 打开新窗口的两种方法
  4. 【CentOS Linux 7】实验1【Linux文件目录管理】
  5. 人生苦短,我学python之python+selenium select下拉框
  6. WMRouter:美团外卖Android开源路由框架
  7. leetcode hot100(第二部分) + python(c++)
  8. python︱写markdown一样写网页,代码快速生成web工具:streamlit 缓存(五)
  9. avascript 运动中Offset的bug解决方案
  10. [2018.07.21 T2] 离家出走
  11. JAVA程序设计教程-第2版-雍俊海 介绍以及 PDF+源代码+ppt 下载链接
  12. 再也不用花一天时间做ppt了
  13. 微信小程序在聊天中如何插入表情?
  14. 二叉树(知道中序遍历和后序遍历得到先序遍历)
  15. 30行python代码实现豆瓣电影排行爬取
  16. 3月4日作业总结,成绩
  17. xp计算机u盘重装系统,u启动一键u盘安装原版XP系统教程_u启动
  18. 物联网医疗康复AI软件项目找团队合作
  19. CS5298 Type-C/DP1.4 到 HDMI 2.1转换芯片|TYPEC转HDMI2.1转换芯片|DP1.4转HDMI2.1转换芯片
  20. 百度与小米在一起了,双方到底想干啥?

热门文章

  1. springboot+vue搭建简单的聊天网站,从0到上线(腾讯云)
  2. CSS常考面试题资料
  3. Docker 部署ElasticSearch + Kibana
  4. 精度更高,视野更大的Photoneo3D相机
  5. Notes Fifth Day-渗透攻击-红队-信息收集
  6. 微小宝公众号排行榜_榜单 广东省技工院校微信公众号排行榜(50期)
  7. 网康科技-下一代防火墙 rce
  8. 请问有什么控件可以方便的实现呢
  9. 2022-12-09 Ubuntu16.4中访问另一台Ubuntu samba共享出来的目录方法
  10. 哈尔滨理工大学软件与微电子学院程序设计竞赛 H.Maze