Python-實現(xiàn)火車票查詢工具_第1頁
Python-實現(xiàn)火車票查詢工具_第2頁
Python-實現(xiàn)火車票查詢工具_第3頁
Python-實現(xiàn)火車票查詢工具_第4頁
Python-實現(xiàn)火車票查詢工具_第5頁
已閱讀5頁,還剩15頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、Python實現(xiàn)火車票查詢工程簡介當(dāng)你想查詢一下火車票信息的時候,你還在上 12306 官網(wǎng)嗎?或是翻開你 里的 APP?下面讓我們來用 Python 寫一個命令行版的火車票查看器, 只要在命令行敲一行命令就能獲得你想要的火車票信息!如果你剛掌握了 Python 根底,這將是個不錯的小練習(xí)。1.1 知識點· Python 根底知識的綜合運用· docopt、requests、colorama 及 prettytable 庫的使用· setuptools 的使用1.2 效果截圖二、接口設(shè)計一個應(yīng)用寫出來最終是要給人使用的,哪怕只是給你自

2、己使用。所以,首先應(yīng)該想想你希望怎么使用它?讓我們先給這個小應(yīng)用起個名字吧,既然及查詢票務(wù)信息,那就叫它 tickets 好了。我們希望用戶只要輸入出發(fā)站,到達站以及日期就讓就能獲得想要的信息,比方要查看10月30號上海-北京的火車余票, 我們只需輸入:$ python tickets.py 上海 北京 2021-10-30 注意:上面的日期包括后面的是筆者寫文章時確定的日期,當(dāng)你在做這個工程的時候可能要根據(jù)當(dāng)前時間做適當(dāng)調(diào)整。轉(zhuǎn)化為程序語言就是:$ python tickets.py from to date 另外,火車有各種類型,高鐵、動車、特快、快速和直達,我們希望可

3、以提供選項只查詢特定的一種或幾種的火車,所以,我們應(yīng)該有下面這些選項:· -g 高鐵· -d 動車· -t 特快· -k 快速· -z 直達這幾個選項應(yīng)該能被組合使用,所以,最終我們的接口應(yīng)該是這個樣子的:$ python tickets.py -gdtkz from to date 接口已經(jīng)確定好了,剩下的就是實現(xiàn)它了。三、代碼實現(xiàn)首先安裝一下實驗需要用到的庫:$ sudo pip3 install requests prettytable docopt colorama · requests,使用 Python 訪問 資源的必備庫

4、。· docopt,Python3 命令行參數(shù)解析工具。· prettytable, 格式化信息打印工具,能讓你像 MySQL 那樣打印數(shù)據(jù)。· colorama,命令行著色工具3.1 解析參數(shù)Python有很多寫命令行參數(shù)解析工具,如 argparse, docopt, click,這里我們選用的是 docopt這個簡單易用的工具。docopt 可以按我們在文檔字符串中定義的格式來解析參數(shù),比方我們在 tickets.py 中寫下下面的內(nèi)容實驗樓環(huán)境下,通過點擊右下角的鍵盤小圖標(biāo)可以選擇中文輸

5、入法:# coding: utf-8"""命令行火車票查看器Usage: tickets -gdtkz <from> <to> <date>Options: -h,-help 顯示幫助菜單 -g 高鐵 -d 動車 -t 特快 -k 快速 -z 直達Example: tickets 北京 上海 2021-10-10 tickets -dg 成都 南京 2021-10-10"""from docopt import docoptdef cli(): """command-l

6、ine interface""" arguments = docopt(_doc_) print(arguments)if _name_ = '_main_': cli()上面的程序中, docopt 會根據(jù)我們在 docstring 中的定義的格式自動解析出參數(shù)并返回一個字典,也就是 arguments, 我們打印出了這個字典的內(nèi)容。下面我們運行一下這個程序, 比方查詢一下10月30號從成都到南京的動車和高鐵:$ python tickets.py -dg 成都 南京 2021-10-10 我們得

7、到下面的參數(shù)解析結(jié)果:3.2 獲取數(shù)據(jù)參數(shù)已經(jīng)解析好了,下面就是如何獲取數(shù)據(jù)了,這也是最主要的局部。首先我們用實驗樓環(huán)境的Firefox瀏覽翻開 12306,進入余票查詢頁面,按下 F12 翻開開發(fā)者工具,選中 Network 一欄,在查詢框中隨便查詢一次,我們在調(diào)試工具觀察下請求和響應(yīng):注意到上面的請求 URL ,它是由基 URL  s:/kyfw.12306 /otn/lcxxcx/query 加四個參數(shù)構(gòu)成的,這四個參數(shù)分別代表,查詢的類型成人?學(xué)生?,日期,出發(fā)車站,到達車站:再來看看響應(yīng):返回的是JSON格式的數(shù)據(jù)

8、! 我們翻開返回的數(shù)據(jù)看看:可以看到一列火車的數(shù)據(jù)用 Python 的語言說就是一個字典。接下來問題就簡單了,我們只需要利用這個接口, 構(gòu)建請求URL然后解析返回的JSON數(shù)據(jù)就可以了。但是我們發(fā)現(xiàn),URL里面參數(shù) from_station 和 to_station 并不是漢字,而是一個代號,而我們想要輸入的是漢字,我們要如何獲取代號呢?我們翻開網(wǎng)頁源碼看看有沒有什么發(fā)現(xiàn)。果然,這里有個關(guān)于 station 的文件,翻開看看:station_names 是一個很長的字符串, 這里面貌似是包含了所有車站的中文名,拼音,簡寫和代號等信息。但是這些信

9、息擠在一起,而我們只想要車站的拼音和大寫字母的代號信息,怎么辦呢? 正那么表達式!我們寫個小腳本來匹配提取出想要的信息吧, 在parse_station.py中:import reimport requestsfrom pprint import pprint url = ' s:/kyfw.12306 /otn/resources/js/framework/station_name.js?station_version=1.8971'response = requests.get(url, verify=False)stations = re.findall(u'(u

10、4e00-u9fa5+)|(A-Z+)', response.text)pprint(dict(stations), indent=4)我們運行這個腳本,它將以字典的形式返回所有車站和它的大寫字母代號, 我們將結(jié)果重定向到 stations.py 中,$ python3 parse_station.py > stations.py 我們?yōu)檫@個字典加名字,stations, 最終,stations.py文件是這樣的:現(xiàn)在,用戶輸入車站的中文名,我們就可以直接從這個字典中獲取它的字母代碼了:from stations import stationsdef cli(

11、): arguments = docopt(_doc_) from_station = stations.get(arguments'<from>') to_station = stations.get(arguments'<to>') date = arguments'<date>' # 構(gòu)建URL url = ' s:/kyfw.12306 /otn/lcxxcx/query?purpose_codes=ADULT&queryDate=&from_station=&to_st

12、ation='.format( date, from_station, to_station )萬事俱備,下面我們來請求這個URL獲取數(shù)據(jù)吧!這里我們使用 requests 這個庫, 它提供了非常簡單易用的接口,import requestsdef cli(): # 添加verify=False參數(shù)不驗證證書 r = requests.get(url, verify=False) print(r.json()從結(jié)果中,我們可以觀察到,與車票有關(guān)的信息需要進一步提取:def cli(): . r = requsets.get(url); print(r.json()

13、我們已經(jīng)知道該請求返回的是JSON數(shù)據(jù), 使用 requests 提供的 r.json() 可以將 JSON 數(shù)據(jù)轉(zhuǎn)化為 Python 字典,上面我們打印了這個字典,運行程序,我們看到:圖中方框是一個字典,字典中的數(shù)據(jù)也就是一班列車的信息, 也就是說所有列車的信息都在一個包含多個字典的列表中, 而這個列表又嵌套了2個字典,就是圖中的2個橢圓,所以,我們需要的信息應(yīng)該這樣來提?。篴vailable_trains = r.json()'data''datas' 3.3 解析數(shù)據(jù)我們封裝一個簡單的類來解析數(shù)據(jù):class Tra

14、insCollection: header = '車次 車站 時間 歷時 一等 二等 軟臥 硬臥 硬座 無座'.split() def _init_(self, available_trains, options): """查詢到的火車班次集合 :param available_trains: 一個列表, 包含可獲得的火車班次, 每個 火車班次是一個字典 :param options: 查詢的選項, 如高鐵, 動車, etc. """ self.available_trains = available_trains s

15、elf.options = options def _get_duration(self, raw_train): duration = raw_train.get('lishi').replace(':', '小時') + '分' if duration.startswith('00'): return duration4: if duration.startswith('0'): return duration1: return duration property def trains(self

16、): for raw_train in self.available_trains: train_no = raw_train'station_train_code' initial = train_no0.lower() if not self.options or initial in self.options: train = train_no, 'n'.join(raw_train'from_station_name', raw_train'to_station_name'), 'n'.join(raw_t

17、rain'start_time', raw_train'arrive_time'), self._get_duration(raw_train), raw_train'zy_num', raw_train'ze_num', raw_train'rw_num', raw_train'yw_num', raw_train'yz_num', raw_train'wz_num', yield train def pretty_print(self): pt = PrettyT

18、able() pt._set_field_names(self.header) for train in self.trains: pt.add_row(train) print(pt)3.4 顯示結(jié)果最后,我們將上述過程進行匯總并將結(jié)果輸出到屏幕上:.class TrainCollection: . .def cli(): """Command-line interface""" arguments = docopt(_doc_) from_station = stations.get(arguments'<from&

19、gt;') to_station = stations.get(arguments'<to>') date = arguments'<date>' url = (' s:/kyfw.12306 /otn/lcxxcx/query?' 'purpose_codes=ADULT&queryDate=&' 'from_station=&to_station=').format( date, from_station, to_station ) # 獲取參數(shù) opti

20、ons = ''.join( key for key, value in arguments.items() if value is True ) r = requests.get(url, verify=False) available_trains = r.json()'data''datas' TrainsCollection(available_trains, options).pretty_print()運行下程序看看效果吧:3.5 著色至此, 程序的主體已經(jīng)完成了, 但是上面打印出的結(jié)果是全是黑白的,很是乏味, 我們來給它添加點顏色吧

21、! 這里我們使用 colorama 這個命令行著色工具:from colorama import init, Fore init() 修改一下程序,將出發(fā)車站與出發(fā)時間顯示為綠色,到達車站與到達時間顯示為紅色:'n'.join(Fore.GREEN + raw_train'from_station_name' + Fore.RESET, Fore.RED + raw_train'to_station_name' + Fore.RESET),'n'.join(Fore.GREEN + raw_train'

22、start_time' + Fore.RESET, Fore.RED + raw_train'arrive_time' + Fore.RESET),現(xiàn)在再運行程序就可以像文章開始的效果圖一樣了!3.6 完整代碼# coding: utf-8"""命令行火車票查看器Usage: tickets -dgktz <from> <to> <date>Options: -h, -help 查看幫助 -d 動車 -g 高鐵 -k 快速 -t 特快 -z 直達Examples: tickets 上海 北京 2021-1

23、0-10 tickets -dg 成都 南京 2021-10-10"""import requestsfrom docopt import docoptfrom prettytable import PrettyTablefrom colorama import init, Forefrom stations import stationsinit()class TrainsCollection: header = '車次 車站 時間 歷時 一等 二等 軟臥 硬臥 硬座 無座'.split() def _init_(self, available_

24、trains, options): """查詢到的火車班次集合 :param available_trains: 一個列表, 包含可獲得的火車班次, 每個 火車班次是一個字典 :param options: 查詢的選項, 如高鐵, 動車, etc. """ self.available_trains = available_trains self.options = options def _get_duration(self, raw_train): duration = raw_train.get('lishi')

25、.replace(':', '小時') + '分' if duration.startswith('00'): return duration4: if duration.startswith('0'): return duration1: return duration property def trains(self): for raw_train in self.available_trains: train_no = raw_train'station_train_code' initial

26、 = train_no0.lower() if not self.options or initial in self.options: train = train_no, 'n'.join(Fore.GREEN + raw_train'from_station_name' + Fore.RESET, Fore.RED + raw_train'to_station_name' + Fore.RESET), 'n'.join(Fore.GREEN + raw_train'start_time' + Fore.RESE

27、T, Fore.RED + raw_train'arrive_time' + Fore.RESET), self._get_duration(raw_train), raw_train'zy_num', raw_train'ze_num', raw_train'rw_num', raw_train'yw_num', raw_train'yz_num', raw_train'wz_num', yield train def pretty_print(self): pt = Pretty

28、Table() pt._set_field_names(self.header) for train in self.trains: pt.add_row(train) print(pt)def cli(): """Command-line interface""" arguments = docopt(_doc_) from_station = stations.get(arguments'<from>') to_station = stations.get(arguments'<to>') date = arguments'<date>' url = (' s:/kyfw.12306 /otn/lcxxcx/query?' 'purpose_codes=ADULT&queryDate=&' 'from_station=&to_station=').format( date, from_station, to_station ) options = ''.join( key for key, value in a

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論