1. 程式人生 > >pythyon爬蟲實現12306查票

pythyon爬蟲實現12306查票

今天接觸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) >")
# 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)
開始爬取資料:本例中利用PrettyTable將解析好的資料已表格形式展現
# 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()報錯是,是因為沒有查詢到資料,只需要再次執行即可