最新12306票務查詢抓取

1. 經過抓包工具發現,station.name.js這個js文件存儲了全部的車站信息,


通過對請求頭的分析,發現請求的url爲:https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9168,但通過測試發現station_version請求的參數對與相應的結果沒有影響,所以爬取過成功直接忽略了請求參數。
抓取站臺信息代碼以下:python

import requests


HEADERS= {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36',
}

def get_station():
    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js'
    res_str = requests.get(url, headers=headers).text.split('=')[-1].strip("'")
    res_dic = {}
    for i in res_str[1:].split('@'):
        res = i.split('|')
        res_dic.update({res[1]: res[2]})
    retrun res_dic

if __name__ == "__main__":
      get_station()

執行結果以下:
git

2.繼續分析車票信息,發現query這個請求就是查詢的火車票的票務信息


經過分析請求的url連接發現上面Cookie有不少,因爲剛開始的時候我並無使用Cookie,發現請求的響應始終獲取不到正確的結果,而後清除遊覽器緩存的全部cookie再次點擊查詢查詢按鈕,抓包以下:

發現只發送了2次ajax請求,可是這兩次響應也都沒有設置cookie,爲何會攜帶上了cookie信息,所以猜想發送ajax請求的時候自動生成了cookie。github

3.查詢cookie是如何生成的

使用search進行全局搜索(快捷鍵ctrl+shift+F),搜索jc_save_fromStation找到以下結果:

而後調出Sources窗口對搜索到的js代碼進行局部搜索jc_save_fromStation,發現jc_save_fromStation是jc_getcookie函數的一個參數,發現以下:

繼續對搜索到的jc_save_fromStation下入斷點進行調試,發現:

而後繼續進行局部搜索jc_setcookie,發現:
,其中前兩個參數就是分別對應着cookie的鍵和值,而且cookie的鍵和值是不會發生變化的,所以判斷js是請求的時候生成是正確的。
使用站長工具:http://tool.chinaz.com/tools/urlencode.aspx對cookie的鍵進行解碼:
解碼以前:

解碼以後:

發現cookie的值就是經過url編碼得到到的:
_jc_save_fromStation="北京,BJP"的編碼 # 出發地名稱,出發地代號的urlEncode的編碼
_jc_save_toStation="上海,SHH"的編碼 # 目的地,目的地代號的urlEncode的編碼
_jc_save_fromDate=2020-11-30 # 出發日期
_jc_save_toDate=2020-11-29 # 查詢的實際時間
_jc_save_wfdc_flag=dc # dc是固定的值ajax

完整代碼實現:

import requests
import time
from urllib import parse

HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36',
}


def get_station():
    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js'
    res_str = requests.get(url, headers=HEADERS).text.split('=')[-1].strip("'")
    res_dic = {}
    for i in res_str[1:].split('@'):
        res = i.split('|')
        res_dic.update({res[1]: res[2]})
    return res_dic


def check(start_addr, end_addr, date):
    url = 'https://kyfw.12306.cn/otn/leftTicket/query'
    stations = get_station()
    start_addr_str = "," + stations[start_addr]
    end_addr_str = "," + stations[end_addr]
    cookie_mode =  '_jc_save_fromStation={}; _jc_save_toStation={}; _jc_save_fromDate={}; _jc_save_toDate={}; _jc_save_wfdc_flag=dc'
    from_cookie = str((start_addr).encode('unicode_escape')).replace(r'\\', '%').strip(r"b'").strip("'") + str(parse.quote(start_addr_str))
    end_cookie = str((end_addr).encode('unicode_escape')).replace(r'\\', '%').strip(r"b'").strip("'") + parse.quote(end_addr_str)
    from_date = date
    save_date = time.strftime("%Y-%m-%d", time.localtime(time.time()))
    cookie = cookie_mode.format(from_cookie, end_cookie, from_date, save_date)
    HEADERS['Cookie'] = cookie
    params = {
        'leftTicketDTO.train_date': date,
        'leftTicketDTO.from_station': start_addr_str.strip(','),
        'leftTicketDTO.to_station': end_addr_str.strip(','),
        'purpose_codes': 'ADULT',
    }
    response = requests.get(url, params=params, headers=HEADERS)
    print(response.text)


check('北京', '上海', '2020-11-30')

代碼結果:

結果總算是能夠正常的拿到了,具體的代碼優化過程就不在這裏繼續寫了,具體的項目能夠去https://github.com/MingHao-homes/Ticket-grabbing-12306查看緩存

相關文章
相關標籤/搜索