python爬火车票_python爬取12306火车余票程序(一)
首先說一下大體的流程,簡單的流程圖如下:
1、獲取URL
打開12306余票查詢的 網頁鏈接,瀏覽器(我用的chrome)按F12來分析請求。輸入要查詢的起始地點和時間后點擊查詢,可以看到右側抓到的鏈接信息:
這個Request URL?便是我們需要的請求鏈接:?Request URL:
大體有以下四部分組成:
(1)train_date:發車時間,注意格式是“yyyy-mm-dd”
(2)from_station:出發站點標識
(3)to_station:到達站點標識
(4)purpose_code:購票類型,有成人(ADULT)、學生(0X00)等。
2、獲取站點標識
出發站和到達站是用字母簡寫標識的,我們需要找到他們的對應關系。網頁源代碼搜索“station_version”可以找到如下一個鏈接,打開后可以看到,里面保存的就是這站點名稱和字母縮寫的對應關系。
格式為:"xxx|漢語名稱|代碼標識|yyy "。我們需要做的就是將這些信息保存到字典中備用,進行對名稱進行轉化。
以上兩部分的代碼如下:
import re
import requests
STATION_DICT_URL = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9088'
def getStation(sta):
str = requests.get(STATION_DICT_URL).text
#匹配中文的正則表達式
area = re.findall("([\u4E00-\u9FA5]+)\|([A-Z]+)",str)
area = dict(area)
if sta in area:
return area[sta]
'''
url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2019-01-10&leftTicketDTO.from_station=SZH&leftTicketDTO.to_station=WFK&purpose_codes=ADULT
'''
def getUrl(from_sta, to_sta, date):
url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=' + date + '&leftTicketDTO.from_station=' + from_sta + '&leftTicketDTO.to_station=' + to_sta + '&purpose_codes=ADULT'
return url
3、分析返回結果
拼裝出上述鏈接后直接request.get即可獲得回應數據:
我這里用了一個谷歌瀏覽器的Jsonview插件,下載地址,可以比較直觀的展現Json數據。對返回的Json數據仔細比較分析就可以得到對應關系。
map存儲的是查詢到結果相關的站點標識,result里面保存的是余票信息、時間信息等。主函數如下:
if __name__ == '__main__':
arguments = docopt(__doc__, version='TicketsQuery v1.0')
from_sta = arguments.get("")
to_sta = arguments.get("")
date = arguments.get("")
#將漢字轉換為特定編碼
from_sta_code = getStation(from_sta)
to_sta_code = getStation(to_sta)
#拼接url 用來get
url = getUrl(from_sta_code, to_sta_code, date)
print(url)
#請求url
html = requests.get(url)
html.encoding = 'utf-8'
print(html.text)
#網頁返回200 Ok進行解析
if html.status_code == 200:
#獲取json
try:
res = html.json()["data"]["result"]
#print(res)
sta_dict = html.json()["data"]["map"] #獲得到一個字典 用于站點的漢字和字符標記轉換
#做表
table=PrettyTable(["車次","出發站","到達站","出發時間","到達時間","歷時","特等座","一等座","二等座","軟臥","硬臥","軟座","硬座","無座"])
for data in res:
list = data.split("|") #分割,獲取所有信息填入的list
#print(list)
if list[1]=='列車停運': #根據json 挨個分析
continue
line_no = list[3]
from_sta = list[6]
to_sta = list[7]
start_time = list[8]
stop_time = list[9]
cost_time = list[10]
#字符串 賦值 : or 兩個都有值,取第一個,第一個沒有值,取第二個
TDZ=list[32] or "--" #特等座
YDZ=list[31] or "--" #一等座
EDZ=list[30] or "--" #二等座
RW=list[23] or "--" #軟臥
YW=list[28] or "--" #硬臥
RZ=list[27] or "--" #軟座
YZ=list[29] or "--" #硬座
WZ=list[26] or "--" #無座
#表格添加列
table.add_row([line_no, sta_dict[from_sta], sta_dict[to_sta], start_time, stop_time, cost_time, TDZ, YDZ, EDZ, RW, YW, RZ, YZ, WZ])
print (table)
except Exception as e:
print('Error:',e)
為了信息直觀方便的輸入輸出,使用了docopt 和 prettytable兩個庫。
最終效果如下:
代碼上傳至GitHub:下載地址? ? 目前是截止2019-1-2測試可用,由于12306網站鏈接時常更新,可能過后不可用。再改下就好~
總結
以上是生活随笔為你收集整理的python爬火车票_python爬取12306火车余票程序(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql中int(m)_mysql中i
- 下一篇: mysql事务实战_MySQL实战45讲