Python 实现火车票查询工具
一. 实验介绍
通过python3实现一个简单的命令行版本的火车票查询工具,用实际中的例子会更感兴趣,不管怎么样,既练习了又可以自己使用。
1. 知识点:
- Python 基础知识的综合运用
- docopt, requests, colorama, prettytable 库的使用
- setuptools 的使用
2. 效果截图:
二. 接口设计
接口我们就按照12306官网的查询格式如下:
程序名: pickets
查询方式: 程序名 出发地 目的地 出发日
火车类型:
-g 高铁
-d 动车
-t 特快
-k 快速
-z 直达
最终组合接口为:
python pickets.py [-gdtkz] from to date
三. 代码实现
根据接口设计需要安装的库:
G:Python项目实战pickets>pip3 install requests prettytable docopt colorama
requests: 使用Python访问HTTP资源的必备库
详细使用请访问:http://www.cnblogs.com/python-nameless/p/6013647.html
prettytable: 可以将打印内容格式化为像MySQL一样的输出
详细使用请访问:http://www.cnblogs.com/python-nameless/p/6013698.html
docopt:命令行参数解析工具
详细使用请访问:https://github.com/docopt/docopt
colorama: 命令行着色工具
1. 解析参数
docopt模块可以按照我们自己在文档字符串定义的格式来解析参数,如下:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # __Author__: Hong 4 5 """火车票查询工具 6 7 Usage: 8 tickets [-gdtkz] <from> <to> <date> 9 10 注意:Usage为固定词汇,其他报错。 11 12 Options: 13 -h,--help 显示帮助菜单 14 -g 高铁 15 -d 动车 16 -t 特快 17 -k 快速 18 -z 直达 19 20 Example: 21 tickets 北京 大同 2016-08-28 22 tickets -t 北京 大同 2016-08-28 23 """ 24 from docopt import docopt 25 from requests import request 26 import prettytable 27 import colorama 28 29 30 def cli(): 31 """command-line interface""" 32 33 arguments = docopt(__doc__) 34 print(arguments) 35 36 if __name__ == '__main__': 37 cli()
由上面的程序中,docopt会根据我们在docstring中定义的格式解析参数并返回一个字典(arguments),例如查询北京到大同的特快如下:
G:Python项目实战pickets>python pickets.py -tk 北京 大同 2016-10-30
参数解析结果:
1 G:Python项目实战pickets>python pickets.py -tk 北京 大同 2016-10-30 2 {'-d': False, 3 '-g': False, 4 '-k': True, 5 '-t': True, 6 '-z': False, 7 '<date>': '2016-10-30', 8 '<from>': '北京', 9 '<to>': '大同'}
2. 获取数据
参数解析好以后,我们可以通过12306官网获取我们需要的数据,IE浏览器打开12306官网的查票系统,输入出发地,目的地,日期,查询,通过F12开发者模式找到请求地址(刷新一次):
通过此请求URL,我们可以看到有我们需要的信息,或者直接点击参数查看:
可以看到参数为:出发地 查询类型(成人,学生) 日期 目的地
通过正文可以看到:返回一个json格式的数据,即一个字典,里边包括了各个站点的中文名和站点代号,我们可以利用这个接口来获取。
打开此页的源码(在页面右击选择查看源码):
查看一下具体内容:
复制此链接前边需要加一级域名https://kyfw.12306.cn打开, 如下:
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971
station_names是一个很长的字符串,里边包括了所有车站中文名,拼音,简写,代号等,这里可以看到有很多信息,我们提取我们需要的信息中文字母和代号信息,我们用正则表达式来提取:
写一个简单的脚本抓取(parse_station.py):
#!/usr/bin/env python # -*- coding: utf-8 -*- # __Author__: hong import re import requests from pprint import pprint # pprint: 格式化输出 url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8971' #获取URL response = requests.get(url, verify=False) #正则提取中文字母和代号 stations = re.findall(u'([u4e00-u9fa5]+)|([A-Z]+)', response.text) # indent:定义打印信息的缩进为4个空格 pprint(dict(stations), indent=4)
提出数据为一个dict 重定向到一个文件里(stations.py)定义字典名如下:
注意:
字典前边定义函数名为stations,默认使用utf-8中文显示乱码,可以切换为GBK。