Python Requests 12306列車車次信息爬取


導(dǎo)入需要的模塊

import  requests
import  re
import ssl

a = input("出發(fā)地:")
b = input("目的地:")
c = input("出發(fā)日期:")

#表示忽略未經(jīng)核實(shí)的SSL證書認(rèn)證,防止因?yàn)閔ttps認(rèn)證導(dǎo)致訪問失敗
ssl._create_default_https_context=ssl._create_unverified_context

當(dāng)然我們還有另一種的方法繞過ssl認(rèn)證
當(dāng)網(wǎng)頁需要ssl驗(yàn)證的時(shí)候,正常爬取會(huì)出現(xiàn)SSLError報(bào)錯(cuò),表示證書錯(cuò)誤,我們通過設(shè)置 verity 參數(shù) 為 False 來避免這個(gè)錯(cuò)誤

import requests

a = requests.get(“[https://www.12306.cn](https://www.12306.cn)”,verify=False)
print(a.status_code)

不過我們會(huì)發(fā)現(xiàn)一個(gè)警告,我們可以通過日志捕獲警告的方式,屏蔽警告

import requests
import logging

logging.captureWarnings(True)

a = requests.get(“[https://www.12306.cn](https://www.12306.cn)”,verify=False)
print(a.status_code)

構(gòu)造requests請求包


由于12306列車查詢界面使用的是GET傳輸,所以我們直接構(gòu)造url

def get_station():
    #12306的城市名和城市代碼js文件和URL
    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9143'
    r = requests.get(url)
    pattern = u'([\u4e00-\u9fa5]+)\|([A-Z]+)'#\u4e00-\u9fa5是所有漢字的Unicode編碼范圍
    result = re.findall(pattern,r.text)#按正則表達(dá)式匹配
    station=dict(result)
    #print(station)
    return station

#生成查詢的URL
def get_query_url(text):
    #城市名代碼查詢字典
    #key:城市名 value:城市代碼,如:{'北京北': 'VAP', '北京東': 'BOP', '北京': 'BJP'}
    try:
        from_station_name= a
        to_station_name= b
        date= c
        from_station = text[from_station_name] #將城市名轉(zhuǎn)換為城市代碼
        to_station = text[to_station_name]
    except:
        date,from_station,to_station = '--','--','--'
    #API URL構(gòu)造
    url = (
        'https://kyfw.12306.cn/otn/leftTicket/query?'
        'leftTicketDTO.train_date={}&'
        'leftTicketDTO.from_station={}&'
        'leftTicketDTO.to_station={}&'
        'purpose_codes=ADULT'
    ).format(date,from_station,to_station)
    return url
    #print (url)

發(fā)送請求,并將爬取到的信息進(jìn)行整理

#獲取車次信息
def query_train_info(url,text):
    #headers部分請務(wù)必參照自己的瀏覽器填寫,以下參數(shù)少一個(gè)都會(huì)被12306判定為爬蟲
    headers = {
        'Host':'kyfw.12306.cn',
        'Referer': 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%E6%B2%88%E9%98%B3,SYT&ts=%E9%9E%8D%E5%B1%B1,AST&date=2020-06-24&flag=N,Y,Y',
        'Pragma': 'no-cache',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'Accept-Language': 'zh-cn',
        'Accept-Encoding': 'br, gzip, deflate',
        'Cookie':'RAIL_DEVICEID=JPQw57vzB656fgPjLHskLw9ssSt400F26k4-Z1PKlzY-Zn5nk1sjEWvuyBUCsq2Tc8FFmYD4OXSTlTxjm0tOf_0ZDzbjqMRIzwTUA-bGOmVccwg9K4x7zj7ZTrrDPsjvsXeUeQjdylKWVNREuZAZ46VS0nViglny; RAIL_EXPIRATION=1592564633156; BIGipServerindex=1138295050.43286.0000',
        'If-Modified-Since': '0',
        'Cache-Control': 'no-cache',
        'X-Requested-With': 'XMLHttpRequest',
        'User-Agent':
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36'
}
    try:
        r = requests.get(url,headers = headers)
        #print(r.json())
        #獲取返回json數(shù)據(jù)中data字段的result結(jié)果
        raw_trains = r.json()['data']['result']
        for raw_train in raw_trains:
            #循環(huán)遍歷每輛列車的信息
            data_list = raw_train.split('|')

            #車次號(hào)碼
            train_no = data_list[3]
            #出發(fā)站
            from_station_code = data_list[6]
            from_station_name = a
            #終點(diǎn)站
            to_station_code = data_list[7]
            to_station_name = b
            #出發(fā)時(shí)間
            start_time = data_list[8]
            #到達(dá)時(shí)間
            arrive_time = data_list[9]
            #總耗時(shí)
            time_fucked_up = data_list[10]
            #一等座
            first_class_seat = data_list[31] or '--'
            #二等座
            second_class_seat = data_list[30] or '--'
            # 軟臥
            soft_sleep = data_list[23] or '--'
            # 硬臥
            hard_sleep = data_list[28] or '--'
            # 硬座
            hard_seat = data_list[29] or '--'
            # 無座
            no_seat = data_list[26] or '--'
            # 打印查詢結(jié)果
            info = (
                '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n'
                '|車次:{} | 出發(fā)站:{} | 目的地:{} | 出發(fā)時(shí)間:{} | 到達(dá)時(shí)間:{} | 消耗時(shí)間:{} | '
                '| 一等座:「{}」| 二等座:「{}」| 軟臥:「{}」| 硬臥:「{}」| 硬座:「{}」| 無座:「{}」|\n'
                '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'.format(train_no,from_station_name,to_station_name,start_time,arrive_time,
                                     time_fucked_up,first_class_seat,
                                     second_class_seat,soft_sleep,hard_sleep,hard_seat,no_seat)
            )
            print(info)
            
    except Exception as e:
        print(e)

if __name__ == '__main__':
    text = get_station()
    url = get_query_url(text)
     #循環(huán)查詢,知道查詢到想要的車次有票終止
    '''while True:
        time.sleep(1)#刷票頻率
        if query_train_info(url,text):
            break'''
    query_train_info(url,text)

效果如下

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容