还原整个思路,遇到的一些问题也会写出来,纯新手向,因为打包在了一个类里,所以单独拷贝一个函数可能会有些问题,后面有完整代码地址,如有错误可以指正- -有问题也可以留言,后面写的有些赶,可以去完整源代码中看看
截至2018/10/9 0:15代码还是有效的

环境:

python3.6
涉及的库:
requests
json
prettytable
re
pprint
1.url分析
先打开12306的余票查询,我用的是火狐浏览器,按F12打开调试工具选择network(网络)选项,选择出发地,目的地,日期,点击查询

(小白问题:调试窗口里啥也没有是因为 你一番操作猛如虎,结果完事后想起:哎?调试窗口没打开!)
右上角有一排选项,咱选js,xhr 然后从这一条条里找出我们需要的链接(点的时候在右边选择响应,可以看到这条请求返回啥)哇塞!你找到一串data,里面还有各种车票的信息,好了,就是你了:
https://kyfw.12306.cn/otn/leftTicket/queryA?leftTicketDTO.train_date=2018-10-23&leftTicketDTO.from_station=HZH&leftTicketDTO.to_station=RZH&purpose_codes=ADULT

PS:找json链接这种活就看经验了,老手可能马上就能找到,新手可能就要一条条点(汗~~)我这给一个快速的方法:进入余票查询界面,选择好出发地和目的地及日期,点击查询,好!然后再打开F12调试界面在点查询!哇塞只有1条而且就是我们需要的!(深入原因的话就是在你打开了调试界面后你只进行了这一条查询的post请求,而返回的当然就是你要的了)

好,继续正题,我们来观察这条json的链接,很容易明白那些参数吧,如下:
https://kyfw.12306.cn/otn/leftTicket/queryA?leftTicketDTO.train_date=2018-10-23&leftTicketDTO.from_station=HZH&leftTicketDTO.to_station=RZH&purpose_codes=ADULT
leftTicketDTO.train_date=日期
leftTicketDTO.from_station=出发点的地点码
leftTicketDTO.to_station=目的地的地点码
purpose_codes=票的种类
2.获取车站对照字典
上文链接中有两个参数是地点码,即一个地名对应一个值,一开始我是直接下载了网上(baidu喽)的一个字典,然后最后写完.不对!我靠!而且调试半天定位到字典错了!(这么多的地名偏偏被窝测试到错误的也是没谁了…)

好!自己动手!

import requests
import re
#生成字典 运行一次后抛弃之~~~
def new_dictionary():url="https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9069"station_namesweb=requests.get(url)stationdic = re.findall(r'([\u4e00-\u9fa5]+)\|([a-zA-Z]+)', station_namesweb.text)stationdic=dict(stationdic)print(stationdic)
new_dictionary()

requests请求,json打包,正则提取,over!
打印出一个字典复制然后在一个文件里就ok了(上面代码中的url其实也是一样找的,可以试试手去找找看)哈哈,其实这也是今天整个工程的浓缩版吧,思路也是差不多的
3.输入出发点,目的地,时间,获得需要的查询链接
废多看码!!!

    def getUrl(self):startflag = Falseendflag = Falsewhile startflag == False:start = input("请输入始发地:\n")startflag = stations.__contains__(start)if startflag == False:print('始发地输入错误!')while endflag == False:end = input("请输入目的地:\n")endflag = stations.__contains__(end)if endflag == False:print('目的地输入错误!')self.date = input("请输入日期(格式为xxxx-xx-xx):\n")url = 'https://kyfw.12306.cn/otn/leftTicket/queryA?leftTicketDTO.train_date=' \+ self.date + '&leftTicketDTO.from_station=' \+ stations[start] + '&leftTicketDTO.to_station=' \+ stations[end] + '&purpose_codes=ADULT'return url

4.获取车辆信息
因为12306在这里没做啥验证所以可以直接请求,不妨直接在浏览器里看一下,emmm是不是头都大了!!!

车辆的信息都在这里了,用|分隔开,我们要做的就是从里面提取出我们想要的信息,emmm其实我花的时间最多的是在这里,因为要一一对应知道每个信息代表什么,而我又找不到那么一辆每个信息都齐全的车来让我对照…只能用好几辆的信息来对比喽(还不一定是对的,眼力有限)…我的眼睛!!!

乱码|预订|030000K5540E|K551|MDB|RZH|HZH|RZH|02:31|10:50|08:19|Y|乱码|20181021|3|B2|44|52|0|0||||无|||无||有|10|||||10401030|1413|0

上代码:

    def getData(self,url):dataweb = requests.get(url)datajson = json.loads(dataweb.text)datatrains = datajson['data']['result']restations=datajson['data']['map']#地点缩写:地点全称的字典dataans = []for train in datatrains:per = {'train_no': '','from_station_no': '','to_station_no': '','seat_types': '','chufazhan':'','dadaozhan':'','checi': '','chufasj': '','didasj': '','lishi': '','erdeng': '','yideng': '','shangwu': '','wuzuo':''}train = train.split('|')per['train_no'] = train[2]per['from_station_no'] = train[16]per['to_station_no'] = train[17]per['seat_types'] = train[35]per['chufazhan']=train[6]per['dadaozhan']=train[7]#将得到站点名字由缩写转换全称per['chufazhan']=restations[per['chufazhan']]per['dadaozhan']=restations[per['dadaozhan']]per['checi'] = train[3]per['chufasj'] = train[8]per['didasj'] = train[9]per['lishi'] = train[10]per['erdeng'] = train[30]per['yideng'] = train[31]per['shangwu'] = train[32]per['wuzuo']=train[26]for value in per:if (per[value] == ''):per[value] = '-'dataans.append(per)return dataans

PS:这里有个问题要说明下:比如我朋友温州-金华,而金华有两个站,他只要其中一个站的,所以我们得显示出出发站和抵达站到底是哪个,但是在信息中我们获得地点是一个码而不是一个站的名字,而我们的字典中是 {名字:码},一开始我想要不干脆再做个反转的字典,后来往上翻的时候发现:原来上面已经给我们了!解决!计划通~

5.获取票价信息
票价的url是另外一条了,获取方式同上上,老方法请求,解析,打包

    def GetPrice(self,train_no,from_station_no,to_station_no,seat_types,date,price):url = 'https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice?train_no=' \+ train_no + '&from_station_no=' \+ from_station_no + '&to_station_no=' \+ to_station_no + '&seat_types=' \+ seat_types + '&train_date=' + datepriceweb=requests.get(url)pricejson=json.loads(priceweb.text)pricedata=pricejson['data']shangwu=pricedata.__contains__('A9')#商务yideng=pricedata.__contains__('M')#一等erdeng=pricedata.__contains__('O')#二等wuzuo=pricedata.__contains__('WZ')#无座if shangwu:price['shangwu']=pricedata['A9']else :price['shangwu']=''if yideng:price['yideng']=pricedata['M']else :price['yideng']=''if erdeng:price['erdeng']=pricedata['O']else :price['erdeng']=''if wuzuo:price['wuzuo']=pricedata['WZ']else :price['wuzuo']=''return price

6.输出
用了prettytable库输出表格

    def Print(self):price={'shangwu':'','yideng':'','erdeng':'','wuzuo':'',}table = prettytable.PrettyTable()table.field_names = ["车次","出发站","达到站" ,"出发时间", "抵达时间", "历时", "二等座", "一等座", "商务座","无座"]for per in self.data:price=self.GetPrice(per['train_no'],per['from_station_no'],per['to_station_no'],per['seat_types'],self.date,price)table.add_row([per['checi'],per['chufazhan'],per['dadaozhan'], per['chufasj'], per['didasj'], per['lishi'], per['erdeng']+'\n'+price['erdeng'], per['yideng']+'\n'+price['yideng'],per['shangwu']+'\n'+price['shangwu'],per['wuzuo']+'\n'+price['wuzuo']])print(table)

7.演示

8.完整代码
https://github.com/senjay/12306tickets_and_price_search

12306余票及票价查询相关推荐

  1. (二)、Python查询12306余票:联网查询余票信息并解析

    前一篇–>实现始发站.终点站和出发日期的合法性检验 以下如果有的变量不明白说明在前面的文章已经介绍了,切记! 首先我们来看看每查询一条信息12306网站返回的信息: 请求链接: https:// ...

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

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

  3. 火车票查询系统(一)——利用python实现监控12306余票查询

    最近春运高峰,本人从12月开始买过年回家的火车票,然鹅~现实总是那么残酷,放票时间记不住,要么就是不能实时盯着刷票,外面的软件也不知道靠不靠谱,反正是没买到票,所以一怒之下,自己做一个12306余票查 ...

  4. 12306 余票查询API浅探索

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

  5. 最新Python实现12306余票查询系统

    首先感谢这篇博客的引导,但是这篇文章已经比较旧了,12306进行了改版,源码编排方式有了变化.12306源码获取的方法可以从这篇博客中学习,我在这里主要贴出对于目前最新的12306的Python余票查 ...

  6. Python之12306余票查询

    简单的Python学习,用Python完成一个12306余票查询- Python之12306余票查询 参考资料来自Python 实现火车票查询工具 需要用到的第三方库 requests,使用 Pyth ...

  7. python实现12306余票

    今天就和大家一起来讨论一下python实现12306余票查询(pycharm+python3.7),一起来感受一下python爬虫的简单实践 我们说先在浏览器中打开开发者工具(F12),尝试一次余票的 ...

  8. Java获取12306余票信息(一)

    写在前面 写给自己,也分享给大家. Java获取12306余票信息(一) Java获取12306余票信息(二) Java获取12306余票信息(三) 步骤: 首先找找12306的API 1.打开谷歌浏 ...

  9. python123判断火车票座位_【Python】实现12306余票监控

    首先我们打开12306余票查询窗口 上图红色框的地方,就是表示列车有无车票的地方,我们需要根据这里边的数据来判断. 这里边有一些需要注意的就是,里边表示有票的有字符串"有"和数字& ...

最新文章

  1. gmock学习02---编写自己的Matcher与如何让编译器识别被mock的重载函数
  2. asp.net mvc cookie超时返回登录页面问题
  3. 马云启动“NASA”计划 为未来20年愿景研发核心科技
  4. java学习(12):i++和++i的区别
  5. 比较精确的js倒计时实现
  6. 日期范围 java_JavaJoDA时间-实现日期范围迭代器
  7. docker php安装gd扩展_Linux安装redis及安装php-redis扩展
  8. 【实习之T100开发】T100 单档程序开发(2)添加功能
  9. android其他占用存储,Android如何梳理内存占用情况解决OOM问题
  10. 熬夜整理,最全的Go语言教程来了,快来收藏!
  11. 吉吉影音官网版 v2.7.2.8_p2p播放器​
  12. 配音软件文字转语音有哪些?
  13. python数学符号读法大全_数学符号读法大全
  14. MySQL数据库插入中文时出现Incorrect string value: '\xE6\x97\xB7\xE5\x85\xA8' for column 'sz_name' at row 1...
  15. 苹果手机邮箱imap服务器没有响应,Apple手机的内置电子邮件地址突然显示imap.gmail.com没有响应,无法发送电子邮件...
  16. 基于opencv求直线方程
  17. android正确释放webview,解决Android WebView内存释放
  18. 仿京东手机端地址选择四级地址选择
  19. matlab示波器坐标调整,SIMULINK示波器参数设置
  20. eDairy-我的白日梦

热门文章

  1. !外贸邮件处理经验谈
  2. rhino android js,android rhino
  3. qt treeview展示某一目录_新教材2020上海新高一数学课本目录及增加“数学建模”介绍...
  4. 【C#】数据类型(sbyte,byte,short,ushort,int,uint,long,ulong和char。、、、)
  5. python图像处理报错:RuntimeWarning: overflow encountered in ushort_scalars
  6. 【推荐系统学习】推荐系统架构
  7. Dw2021下载安装教程
  8. Layui之动态选项卡iframe使用
  9. STM32学习--中断
  10. 光复用技术中三种重要技术_三种复用技术