实践项目八:优雅的实时火车票查看器(命令行版)

来源:互联网 发布:高级排序算法 编辑:程序博客网 时间:2024/06/03 22:38

最近在实验楼学到了一个使用的小项目,用python写一个优雅的火车票查看器,不用登陆12306网站,只要在命令行输入一行命令就可以获得你想要的火车票信息。

欣赏效果图

打开12306查询8月13日从郑州到杭州的快速火车的车票
这里写图片描述
下面用命令行版火车票查看器查询同样的信息:
这里写图片描述
有没有感觉到界面很优雅,排版很整齐,还有颜色的区分,虽然不如12306的页面好看,也独具一番特色。

环境

  • 操作系统 : ubuntu 16.04
  • python环境:python 3.5.2

安装python模块

  • requests模块 : 使用Python访问HTTP资源的必备库。
  • docopt模块 : 命令行参数解析工具。
  • prettytable模块 : 格式化信息打印工具,能让你像 MySQL 那样打印数据。
  • colorama模块,命令行着色工具
    这些模块都可以使用下面的语句安装:
    sudo pip3 install [模块名]

设计

1.接口设计

我们要查询票务信息,需要输入出发站,终点站,日期,火车的类型。
从12306官网的余票查询可以看到火车的类型有五种选项:

  • -g 高铁
  • -d 动车
  • -z 直达
  • -t 特快
  • -k 快速
    注意:查询的时候选项可以组合,所以我们的接口为:
    python3 tickets.py 火车类型 出发站 到达站 日期

2.解析参数

解析参数的目的是为了将我们的命令行中的火车类型,出发站,到达站,日期作为已知量,更方便在后面获取url中填充,使缺参url加上已知量组成我们要查询信息的url。不懂的话可以看下这个小例子:http://blog.csdn.net/xunalove/article/details/77040819#t7

3.获取数据和解析数据:

要获取信息需要构造url—>发送请求—>获取数据:

3.1怎么构造url

打开12306官网,查看一次余票,按F12打开开发者工具,选择network里面可以看到两项,第二项就是我们请求返回的url。
这里写图片描述

双击会跳转到如下界面:

这里写图片描述

可以看到result是一个字典,字典里面每一个列表就是一行票务信息。这个url就是需要我们构造的url,
先看看url的构成:
https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-08-13&leftTicketDTO.from_station=ZZF&leftTicketDTO.to_station=HZH&purpose_codes=ADULT

里面有四个参数:

  • train_date=2017-08-13
  • from_station=ZZF
  • to_station=HZH
  • purpose_codes=ADULT

我们发现出发站和目的站并不是汉字而是大写的字符代号。
在网页里面有一个链接带有station-vesion里面包含所有车站的代码。

这里写图片描述

打开连接之后

这里写图片描述

我们需要将这两项提取出来(下面是一种通过url请求的提取方法)构造一个正则表达式模式串,过滤出来我们想要的信息:汉字+字符代号(中间用“|”隔开要进行转义),之后转换为字典类型,分开保存一个为汉字,一个为对应的字符代码,这样在命令行输入汉字的时候根据下面找到对应的汉字的下标找到对应的字符代号。

# !usr/bin/env/python3.5.2# -*- coding:utf-8 -*-import requestsimport re  #正则表达式的包from pprint import pprintdef main():    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9023'    r = requests.get(url, verify = False)    #verify = False 禁止证书验证    #print (r.text)    pattern = u'([\u4e00-\u9fa5]+)\|([A-Z]+)'    #print (re.findall(pattern,r.text))    result = dict(re.findall(pattern, r.text))    #print (dict(result))    print (result.keys())    print (result.values())if __name__ == "__main__":    main()

将运行结果重定向到stations.py里面

 python3 parse_station.py >> stations.py

有了字符代号就可以构造url了

url = ( 'https://kyfw.12306.cn/otn/leftTicket/query?'            'leftTicketDTO.train_date={}&'            'leftTicketDTO.from_station={}&'            'leftTicketDTO.to_station={}&'            'purpose_codes=ADULT').format(date, from_station, to_station)    r = requests.get(url, verify=False)    raw_trains = r.json()['data']['result']

此时我们发送请求得到的数据就如同上图得到的数据,十分混乱,为了得到我们的目标数据,需要对获取的数据进行解析,要解析首先需要知道12306网页是怎么解析信息的,打开开发者工具里面的sources

这里写图片描述

可是看到它是通过for循环实现的,下面还有个参数的信息

这里写图片描述

这部分代码(同时通过prettytable模块将数据格式化,通过colorama模块代码着色部分):

pt = PrettyTable()    pt._set_field_names('车次 车站 时间 历时 商务座 一等座 二等座 高级软卧 软卧 动卧 硬卧 软座 硬座 无座'.split())    for raw_train in raw_trains:        data_list = raw_train.split('|')        train_no = (data_list[3]) #车次        initial = train_no[0].lower()        if initial in options or not options:            from_station_code= (data_list[6])            to_station_code= (data_list[7])            from_station_name =''            to_station_name= ''            start_time = data_list[8]            arrive_time = data_list[9]            time_duration = data_list[10]            normal_seat = data_list[32] or '--'            first_class_seat = data_list[31] or '--'            second_class_seat = data_list[30] or '--'            ssoft_sleep = data_list[21] or '--'            soft_sleep = data_list[23] or '--' #为空显示--            move_sleep = data_list[33] or '--'            hard_sleep = data_list[28] or '--'            soft_seat = data_list[24 ] or '--'            hard_seat = data_list[29] or '--'            no_seat = data_list[26] or '--'            #显示            pt.add_row([                ''.join([Fore.RED + train_no + Fore.RESET]),                '\n'.join([Fore.GREEN + stations.get_name(from_station_code) + Fore.RESET,Fore.YELLOW + stations.get_name(to_station_code)+ Fore.RESET ]),                '\n'.join([Fore.GREEN + start_time + Fore.RESET, Fore.YELLOW + arrive_time + Fore.RESET]),                time_duration,                normal_seat,                first_class_seat,                second_class_seat,                ssoft_sleep,                soft_sleep,                move_sleep,                hard_sleep,                soft_seat,                hard_seat,                no_seat              ])

到这里一个简单实用的实时火车票查看器就完成了。

完整代码:https://github.com/xuna123/Python_pro

遇到的问题

输入命令行,运行结果上面一直输出一段警告性的文字?
这里写图片描述
原因:因为我们使用了”verify = False”是浏览器访问2306时禁止验证。
解决方法:在程序的首部添加如下代码,忽略无害的警告:

from requests.packages.urllib3.exceptions import InsecureRequestWarningrequests.packages.urllib3.disable_warnings(InsecureRequestWarning)

总结

从这个小项目中学到了很多东西,python的参数解析库,格式化库,还有命令行着色小工具,原来命令行也可以优雅的显示。最重要的是学习了项目的思路
如何从开发者工具里找到我们想要的url,怎么根据页面js的显示来设计程序的显示方式,这是我总结的项目的流程:
解析参数—构建url—获取信息—解析信息成想要的信息—设计样式。
参考资料:

https://stackoverflow.com/questions/27981545/suppress-insecurerequestwarning-unverified-https-request-is-being-made-in-pytho
https://www.bilibili.com/video/av12380578/

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 地税网上申报密码忘记了怎么办 国税银行缴款凭证丢失了怎么办 税务局让法人缴税法人不缴会怎么办 税盘忘记清卡怎么办 7年没申报地税怎么办 已报税忘了清卡怎么办 国税报税密码忘了怎么办 有一个月忘报税了怎么办 地税报税密码忘了怎么办 电子税务账号忘记了怎么办 国税ukey密码忘了怎么办 电子税务局显示版本低怎么办 电子税务局2.0不显示打印怎么办 青海建筑三级资质初申是怎么办 欠钱败诉没钱还怎么办 学校退款卡丢了怎么办 学校发的卡掉了怎么办 汇款回执单丢了怎么办 大学交学费的卡丢了怎么办 交学费的银行卡丢了怎么办 学校补助卡丢了怎么办 学校交学费的卡丢了怎么办 采购零星材料无发票怎么办 租房合同弄丢了怎么办 买房的合同丢了怎么办 押金的收据丢了怎么办 房东的合同掉了怎么办 个人档案里单位没有放合同怎么办 签的合同掉了怎么办 一方合同弄丢了怎么办 合同丢了怎么办如何补 签了定金合同对方违约怎么办 医学出生证明丢了怎么办 易通行出站未刷怎么办 炭烧酸奶过期了怎么办 西安建行etc坏了怎么办 电机在设备壳体中拔不出来怎么办 公司变更股东不能亲临现场怎么办? 公司股东变更老股东不签字怎么办 公司变更地址股东不签字怎么办 公司变更股份股东不签字怎么办