資源簡介 (共27張PPT)Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.少兒編程課火車票查詢工具本節課我們來編寫一個爬蟲案例,制作12306火車票查詢工具現在我們開始制作這個查詢工具,首先獲取接口1打開12306,在余票查詢頁面,點擊F12,點擊查詢按鈕在Network中可以看到本次查詢時所有的網絡請求接口12接口參數與網頁填寫數據對應關系:這里第二個接口就是火車票數據查詢接口,如下:https://kyfw./otn/leftTicket/query leftTicketDTO.train_date=2017‐09‐25&leftTicketDTO.from_station=ZZF&leftTicketDTO.to_station=KFF&purpose_codes=ADULT其中:1、leftTicketDTO.train_date表示查詢日期2、leftTicketDTO.from_station:表示出發地編碼3、leftTicketDTO.to_station:表示目的地編碼4、purpose_codes:表示票的類型,ADULT表示成人,如果是學生,則值為0X00訪問這個接口地址,獲取本次查詢的全部JSON數據1返回的數據如下:分析數據接下來,我們對得到的數據進行分析,先規整數據把數據中的result部分(車票部分)存入文本,然后導入到excel(用|分割即可),刪除沒用的列,空列等,最終效果如下:1然后將數據和12306上的查詢數據作對比12306查詢數據如下:12將每列的含義分析出來Python獲取數據分析完數據之后,剩下的工作就是獲取數據然后展示了,首先獲取數據定義獲接口數據的方法,先拼接完整路徑1訪問接口地址2def get_json(url, train_date, from_station, to_station,purpose_codes='ADULT'):url = url + ' leftTicketDTO.train_date=' \+ train_date + '&leftTicketDTO.from_station=' \+ from_station + '&leftTicketDTO.to_station='\+ to_station + '&purpose_codes=' + purpose_codesreq = request.Request(url)分析完數據之后,剩下的工作就是獲取數據然后展示了,首先獲取數據向請求頭添加User—Agent信息,模擬瀏覽器登陸12向請求頭添加Cookie信息req.add_header('User‐Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64)''AppleWebKit/537.36 (KHTML, like Gecko)'' Chrome/56.0.2924.87Safari/537.36')req.add_header('Cookie', 'BLPROV=; JSESSIONID=17F82C085BEAE9774B1D7D18363207AA; ''route=6f50b51faa11b987e576cdb301e545c4; ''BIGipServerotn=1473839370.50210.0000; fp_ver=4.5.1; ''RAIL_EXPIRATION=1505522206734; RAIL_DEVICEID=ngfa0xXXc43AwRde''PQiYKNAXLxgF_0NC4u29FDPVr73XbEdk2jAZXdZmGwbMs5tmX28EVf3pqQWywtJRAN ''yU‐F1F4o1jEN2J8gI5mQVerkJAel9E5ACri_F7hggwk7zmV0IkRNjiH5CA0RFxBPLTsBkmBvAJ9_;'' current_captcha_type=C; _jc_save_fromStation=%u90D1%u5DDE%2CZZF;'' _jc_save_toStation=%u5F00%u5C01%2CKFF; _jc_save_fromDate=2017‐09‐25;'' _jc_save_toDate=2017‐09‐25; _jc_save_wfdc_flag=wf')3向請求頭添加Cookie信息with request.urlopen(req) as f:return json.loads(f.read())然后將數據展示定義數據展方法,首先調用獲取數據方法獲取數據13根據數據分析的結果,將json拆分展示輸出標題24運行程序,結果如下:def list_ticket():json_result = get_json('https://kyfw./otn/leftTicket/query', '2018‐11‐12','ZZF', 'KFF')list_tickets = json_result['data']['result']print("車次", "始發站", "終點站", "出發站", "到達站", "出發時間","到達時間", "歷時", "商務座", "一等座", "二等座", "軟臥","硬臥", "軟座","硬座", "無座", "備注")for ticket in list_tickets:list_ticket_item = ticket.split('|')print(list_ticket_item[3], list_ticket_item[4],list_ticket_item[5], list_ticket_item[6],list_ticket_item[7], list_ticket_item[8],list_ticket_item[9], list_ticket_item[10],list_ticket_item[32], list_ticket_item[31],list_ticket_item[30], list_ticket_item[23],list_ticket_item[28], list_ticket_item[24],list_ticket_item[29], list_ticket_item[26],list_ticket_item[11])輸出結果美化雖然查詢出了結果,但是可以看到車站名稱不是中文而是編碼,而且格式比較亂在余票查詢頁面上右擊 查看源代碼 找到如下js文件:點擊該js文件鏈接可以看到該文件包含了全部的站名稱和對應編碼,根據該文件,前端頁面把從后臺查詢到的編碼轉為了火車站中文名稱12所以,我們就可以根據這個文件中的站名和編碼,自行轉換輸出結果中的編碼新建py文件,使用python獲取站名和對應編碼導入相關庫13編寫正則獲取編碼和站名使用requests獲取數據24獲取到的stations如下:import reimport requestsfrom pprint import pprinturl = 'https://kyfw./otn/resources/js/framework/station_name.js station_version=1.9025'response = requests.get(url, verify=False)stations = re.findall(u'([\u4e00-\u9fa5]+)\|([A-Z]+)', response.text)通過正則獲得的數據是一個有許多元祖組成的列表,每一個元祖包含中文站名和對應編碼[(‘北京北’,‘VAP’),(‘北京東’,‘BOP’),(‘北京’,‘BJP’),(‘北京南’,‘VNP’),(‘北京西’,‘BXP’),(‘廣州南’,‘IZQ’),(‘重慶北’,‘CUW’),(‘重慶’,‘CQW’), (‘重慶南’,‘CRW’),(‘重慶西’,‘CXW’),(‘廣州東’,‘GGQ’), (‘上?!?‘SHH’),(‘上海南’,‘SNH’),(‘上海虹橋’,‘AOH’), (‘上海西’,‘SXH’)……]將這些元祖轉為字典,就能夠方便的轉換編碼和中文站名了,在這之前,我們先來了解兩個python的內置函數dict和zipPython內置函數dict和zipdict(),用于創建、返回一個字典21zip(),參數為可迭代的對象,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。dict(a='a', b='b', t='t') # 傳入關鍵字# 返回值 {'a': 'a', 'b': 'b', 't': 't'}dict(zip(['one', 'two', 'three'], [1, 2, 3])) # 映射函數方式來構造字典# 返回值 {'three': 3, 'two': 2, 'one': 1}dict([('one', 1), ('two', 2), ('three', 3)]) # 可迭代對象方式來構造字典# 返回值 {'three': 3, 'two': 2, 'one': 1}a = [1,2,3]b = [4,5,6]zipped = zip(a,b) # 打包為元組的列表# 返回值 [(1, 4), (2, 5), (3, 6)]接下來,我們就將數據轉為字典將字典的鍵和值反轉21將stations轉為字典stations_dict = dict(stations)dict_res = dict(zip(stations_dict.values(), stations_dict.keys()))3將兩個字典輸出,結果如下:回到12306文件,將編碼替換為中文從文件中導入兩個字典13將結果中的站臺編碼轉為中文,通過對反轉后的字典進行取值實現from .stations_dict import stations_dictfrom .stations_dict_res import stations_dict_resprint( ……stations_dict_res.get(list_ticket_item[4]),stations_dict_res.get(list_ticket_item[5]),stations_dict_res.get(list_ticket_item[6]),stations_dict_res.get(list_ticket_item[7]),……json_result = get_json('https://kyfw./otn/leftTicket/query', train_date, stations_dict.get(from_station),stations_dict.get(to_station))增加中文查詢功能,通過對未反轉的字典進行取值實現2轉換后,輸出結果如下:第三方庫prettytable使用第三方模塊prettytable對控制臺輸出結果美化,首先來安裝打開CMD,輸入pip install prettytable1按下回車,將會自動下載安裝2安裝完成后,將其導入3from prettytable import PrettyTablept = PrettyTable()pt._set_field_names('車次 始發站 終點站 出發站 到達站 出發時間 到達時間 歷時 商務座 一等座 二等座 軟臥 硬臥 軟座 硬座 無座 備注'.split())在結果展示方法中,創建實例,并設置標題3使用第三方模塊prettytable對控制臺輸出結果美化,首先來安裝使用add_row方法將之前直接輸出的內容添加到實例中1最終效果如下:2pt.add_row([list_ticket_item[3], stations_dict_res.get(list_ticket_item[4]),stations_dict_res.get(list_ticket_item[5]),stations_dict_res.get(list_ticket_item[6]), stations_dict_res.get(list_ticket_item[7]),list_ticket_item[8], list_ticket_item[9], list_ticket_item[10], list_ticket_item[32],list_ticket_item[31],list_ticket_item[30], list_ticket_item[23], list_ticket_item[28], list_ticket_item[24],list_ticket_item[29], list_ticket_item[26], list_ticket_item[11]])print(pt)補充說明:如果在請求HTTPS協議時碰到證書問題,則在最前面加上一句:ssl._create_default_https_context = ssl._create_unverified_context1總結Summaryjson數據獲取與解析√requests庫的使用√第三方庫prettytable的使用√Thanks! 展開更多...... 收起↑ 資源預覽 縮略圖、資源來源于二一教育資源庫