pythyon爬蟲實現12306查票
阿新 • • 發佈:2019-01-04
今天接觸python的第二天,猶豫現在剛好是春運階段,所以想用python實現12306搶票功能,猶豫剛接觸python,能力有限,所以只根據百度可以查到的教程,做了一個查票功能
1.實現查票功能,就是爬取12306上的餘票資訊,再在本地進行組織展示
首先開啟12306的餘票查詢介面,分析頁面
從上圖可以看到,當點選查詢功能是所訪問的連線,以及響應資料,我們所要做的就是對響應資料進行解析
2.從地址中我們可以看到查票時所需要傳遞的引數
https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2018-01-16&leftTicketDTO.from_station=VNP&leftTicketDTO.to_station=CDW&purpose_codes=ADULT
leftTicketDTO.train_date為出發日期
leftTicketDTO.from_station為出發地leftTicketDTO.to_station為目的地
purpose_codes=ADULT為成人票
從連結中可以看到 出發地與目的地都為字母,這個是因為12306將所有的地點都做了一個字典存在下面這個js中,可以將地址輸入到瀏覽器上,檢視js中內容
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8964
本人在程式中將以上JS檔案中的內容存到了stations.py中
3.開始今天的正文部分,爬取資料,
先根據improt將所需要的外掛安裝好,然後將所需要的引數準備好:
import stations from Splider12306 import Splider #將地點與所對應的字母對應到字典中,我是將 station = {} for s in stations.station_names.split('@'): if s: tmp = s.split('|') station[tmp[1]] = tmp[2] # train_date = raw_input("請輸入出發時間(格式為2018-01-01) >")開始爬取資料:本例中利用PrettyTable將解析好的資料已表格形式展現# from_station = station[raw_input("請輸入出發城市 >")] # to_station = station[raw_input("請輸入目的城市 >")] # print from_station+ to_station splider = Splider() train_date = '2018-02-11' from_station = 'JNK' to_station = 'ZDN' splider.doCraw(train_date,from_station,to_station,station)
# coding=utf-8 import requests import re import base64 from prettytable import PrettyTable class Splider : def __init__(self): self.headers = { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, sdch, br", "Accept-Language": "zh-CN,zh;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4549.400 QQBrowser/9.7.12900.400" } # stations=r.findall(u'([\u4e00-\u9fa5]+)\|([A-Z]+)',r.json()["data"]["result"])#用正則表示式 來獲取車站的拼音和大小寫字母的代號資訊 # print stations # print isinstance(str(r.json()), unicode) # print r.content.decode('utf-8') def doCraw(self,train_date,from_station,to_station,station) : new_station = {v: k for k, v in station.items()} # print station self.TicketSession = requests.Session() self.TicketSession.headers = self.headers self.TicketSession.verify = False self.query_url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT' %(train_date,from_station,to_station) # r = requests.get(query_url, verify=False) r = self.TicketSession.get(self.query_url) if r.status_code != 200 : print '查詢超時,請稍後再試!' return # print r.status_code # with open('json.txt', 'w') as fp: # fp.write(str(r.json()).decode('utf-8').encode('mbcs')) pt = PrettyTable() header = '車次 出發站 到達站 出發時間 到達時間 時長 一等座 二等座 軟臥 硬臥 硬座 無座 預定'.split() pt._set_field_names(header) if 'result' in r.json()["data"]: rj = r.json()["data"]["result"] c = 0 d = 0 for i in rj: ptrow = [] n = i.split('|') # d += 1 # for n in i.split('|'): # # ptrow.append(x["station_train_code"]) # print'[%s] %s' % (c, n) # c += 1 # c = 0 # # if d>1: # # break # print n[6] # print n[7] ptrow.append(n[3])#車次 ptrow.append(new_station[n[6]])#出發站 ptrow.append(new_station[n[7]])#到達站 ptrow.append(n[8])#出發時間 ptrow.append(n[9])#到達時間 ptrow.append(n[10])#時長 ptrow.append(n[31])#一等座 ptrow.append(n[30])#二等座 ptrow.append(n[23])#軟臥 ptrow.append(n[26])#硬臥 ptrow.append(n[28])#硬座 ptrow.append(n[29])#無座 ptrow.append(n[1]) # 預定 pt.add_row(ptrow) print pt else: print '這兩個站點沒有直達列車'
4.結果展示:當控制檯出現r.json()報錯是,是因為沒有查詢到資料,只需要再次執行即可