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。