




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年四季香酒行業(yè)深度研究分析報告
- 2024-2025學(xué)年高中生物第1單元第1章第2節(jié)植物體內(nèi)的其他激素教案中圖版必修3
- 2024-2025學(xué)年高中政治第3單元思想方法與創(chuàng)新意識第8課唯物辯證法的發(fā)展觀第2框用發(fā)展的觀點看問題課堂訓(xùn)練新人教版必修4
- 2025年中國定象輪行業(yè)市場發(fā)展前景及發(fā)展趨勢與投資戰(zhàn)略研究報告
- 6萬噸亞氨基二乙腈項目可行性研究報告申請報告
- 2025年超高壓液壓控制閥行業(yè)深度研究分析報告
- 活性炭鞋墊行業(yè)深度研究報告
- 生活垃圾處理可行性研究報告建議書
- 2024-2030年中國互聯(lián)網(wǎng)餐飲行業(yè)發(fā)展運行現(xiàn)狀及投資戰(zhàn)略規(guī)劃報告
- 2025年塑料圓柱形項目可行性研究報告
- 中小學(xué)心理健康教育指導(dǎo)綱要(教育部2012年修訂)
- 教育:創(chuàng)造無限可能
- 風(fēng)電場工程強制性條文執(zhí)行計劃
- 茶葉的起源與發(fā)展
- 二年級下冊美術(shù)教案-第19課 剪窗花丨贛美版
- 人保理賠員試題車險查勘定損
- 羅姓姓氏源流和遷徙分布
- 發(fā)展經(jīng)濟學(xué) 馬工程課件 1.第一章 發(fā)展中國家與發(fā)展經(jīng)濟學(xué)
- GB/T 25775-2010焊接材料供貨技術(shù)條件產(chǎn)品類型、尺寸、公差和標(biāo)志
- 房屋建筑學(xué)-01概論
- 2023年大唐集團招聘筆試試題及答案新編
評論
0/150
提交評論