乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      趣玩爬蟲 | 12306火車車次信息爬取分析

       看見就非常 2020-05-20

      點擊上方藍色字關(guān)注 [ 啃餅思錄 ]~

      12306火車車次信息爬取分析

      本篇我們要進行的是12306火車車次信息的爬取分析。都說12306是目前反爬措施最強的網(wǎng)站,的確如此。博主于2017年專門研究過如何爬取并進行了購票分析,費了很大功夫終于成功地搶到了票,但是很不幸,沒過多久12306就進行了大改版,寫過的爬蟲代碼幾乎成為了擺設(shè)。這里只是爬取車次信息,并不進行購票操作,后續(xù)可能會出專門的教程介紹這一塊,本篇文章的重點不在于此。

      分析與爬取過程

      車站名稱信息爬取

      12306網(wǎng)址:https://www.12306.cn/index/,由于我們爬取的是車次信息,因此首先需要知道所有的車站名稱:

      通過觀察,很容易發(fā)現(xiàn)出發(fā)地和到達地都是一個彈窗,由JS控制。我們思考一下,如果想要爬取所有的車站名稱,是不是爬取這個JS彈窗內(nèi)的信息就可以?是的,我們就是這樣做的。首先我們需要登錄賬號,接著進行下面的操作。我們按F12或者直接開啟開發(fā)者模式,先在出發(fā)地隨便選一個車站,然后觀察network處的變化,我們發(fā)現(xiàn)了一個名為station_name_v10026.js的文件,就是這樣:

      接著我們就點擊這個js文件,頁面就跳轉(zhuǎn)到:https://www.12306.cn/index/script/core/common/station_name_v10026.js,我們使用fe助手對代碼進行格式化,發(fā)現(xiàn)這個就是車站名稱控件:

      接下來就是將里面的車站名稱都爬取下面。先點擊這里:漢字 Unicode 編碼范圍,我們發(fā)現(xiàn)一般車站都是常見字,因此使用4E00-9FA5區(qū)間的unicode編碼即可。我們可以使用([\u4e00-\u9fa5]+)\|([A-Z]+)這樣的正則匹配條件來獲取我們需要的諸如北京北': 'VAP'等。相應(yīng)的代碼如下:

      import requestsimport re
      
      headers = {    'Cookie': '',    'Host': 'www.12306.cn',    'Upgrade-Insecure-Requests': '1',    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'}def getStationName():
          # 爬取12306網(wǎng)站所有車站名稱信息
          url = 'https://www.12306.cn/index/script/core/common/station_name_v10026.js'  # 車站信息控件
          r = requests.get(url)
          pattern = '([\u4e00-\u9fa5]+)\|([A-Z]+)'  # 正則匹配規(guī)則
          result = re.findall(pattern, r.text)
          stationName = dict(result)  # 所有車站信息,轉(zhuǎn)換為字典
          print(stationName)    # return stationNamegetStationName()

      運行結(jié)果如下(部分信息):

      {'北京北': 'VAP', '北京東': 'BOP', '北京': 'BJP', '北京南': 'VNP'}

      兩站之間火車票信息查詢

      在前面我們查詢到了所有的車站名稱,接下來我們就是查詢兩站之間火車票的信息了。我們隨意輸入兩個城市,上海和天津,時間更是隨意,如下所示:

      我們注意一下此時url欄的變化,此時url變?yōu)椋?/p>

      我們嘗試輸入北京到上海,再次確認一下url的變化:

      說明后面的flag=N,N,Y是一個常量,如果去掉發(fā)現(xiàn)頁面就不能正常顯示。 也就是說我們需要傳入三個參數(shù):date(日期),from_station(出發(fā)站),to_station(到達站)。我們需要構(gòu)造的url應(yīng)該是這樣: https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=from_station&ts=to_station&date=date&flag=N,N,Y 通過觀察發(fā)現(xiàn),其實不帶車站的字母代號也是可以查詢到票務(wù)信息的:

      所以你可以簡化前面爬取的內(nèi)容,但是我這里就不了,因為我個人比較喜歡這種方式。

      接下來就是構(gòu)建查詢的代碼了,結(jié)合上面查詢到的車站信息,我們就能得到如下代碼:

      import requestsimport re
      
      headers = {    'Cookie': '',    'Host': 'www.12306.cn',    'Upgrade-Insecure-Requests': '1',    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'}def getStationName():
          # 爬取12306網(wǎng)站所有車站名稱信息
          url = 'https://www.12306.cn/index/script/core/common/station_name_v10026.js'  # 車站信息控件
          r = requests.get(url)
          pattern = '([\u4e00-\u9fa5]+)\|([A-Z]+)'  # 正則匹配規(guī)則
          result = re.findall(pattern, r.text)
          stationName = dict(result)  # 所有車站信息,轉(zhuǎn)換為字典
          # print(stationName)
          return stationName
      text =getStationName()def get_query_url(text, date, from_station, to_station):
          # 構(gòu)建用于查詢列車車次信息的url
          # 參數(shù):日期,出發(fā)地,到達地
          # key為車站名稱, value為車站代號
      
          date = date
          from_station = from_station+","+text[from_station]
          to_station = to_station+","+text[to_station]    # 新的url
          url = (        "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&"
              "fs={}"
              "&ts={}"
              "&date={}"
              "&flag=N,N,Y"
          ).format(from_station, to_station, date)
          print(url)
      get_query_url(text,'2019-04-20','上海','天津')

      該程序運行結(jié)果為:

      https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=上海,SHH&ts=天津,TJP&date=2019-04-20&flag=N,N,Y

      拿著這個url去輸入欄訪問一下,發(fā)現(xiàn)可以正常訪問了,頁面顯示票務(wù)信息。

      獲取火車票詳情

      現(xiàn)在我們就是獲取剛才鏈接頁面出現(xiàn)的票務(wù)詳情信息了,我們需要明確獲取的字段信息:車次、出發(fā)站、到達站、出發(fā)時間、到達時間、歷時、商務(wù)/特等座、一等座、二等座、軟臥、硬臥、硬座和無座等。我們拿到剛才生成的url,訪問一下(開啟開發(fā)者模式):

      我們發(fā)現(xiàn)有一個query,然后右邊就是我們查詢的結(jié)果,因此我們可以從這個結(jié)果中取出信息:

      https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2019-04-20&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=TJP&purpose_codes=ADULT

      看到這里,你或許會明白,我們其實構(gòu)造的url最后就是以這個url的查詢結(jié)果的形式返回,那么我們可不可以直接構(gòu)造這個url呢?答案是可以的,那么我們對上面的代碼進行修改一下:

      def get_query_url(text, date, from_station, to_station):
          # 構(gòu)建用于查詢列車車次信息的url
          # 參數(shù):日期,出發(fā)地,到達地
          # key為車站名稱, value為車站代號
      
          date = date
          from_station = text[from_station]
          to_station = text[to_station]    # 新的url
          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)
          print(url)    return url

      運行結(jié)果如下:

      https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2019-04-20&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=TJP&purpose_codes=ADULT

      截圖就是這樣:

      也就說結(jié)果是一個json形式的dict,我們先根據(jù)data這個key取出全部信息,再根據(jù)result這個key取出車次信息。圖中密密麻麻的就是我們需要的車次信息:

      從這個信息中遍歷一下,就能得到我們需要的信息,0代表某一輛車的信息,再從0這個一行中取出我們需要的字段信息即可:

      我們發(fā)現(xiàn)每個字段都是被|給分割的,因此只需要統(tǒng)計這個|的位置就能取出相應(yīng)的信息。相應(yīng)的代碼如下:

      import requests
      
      
      url="https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2019-04-20&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=TJP&purpose_codes=ADULT"r =requests.get(url)
      all_trains = r.json()['data']['result']  # 獲取所有車次信息for one_train in all_trains:  # 遍歷取出每輛車的信息
          data_list = one_train.split('|')
          train_number = data_list[3]  # 車次
          from_station_code = data_list[6]  # 出發(fā)站代號
          from_station_name = '上海' # 出發(fā)站名稱
          to_station_code = data_list[7]  # 到達站代號
          to_station_name = '天津' # 到達站名稱
          go_time = data_list[8]  # 出發(fā)時間
          arrive_time = data_list[9]  # 到達時間
          cost_time = data_list[10]  # 歷時
          special_class_seat = data_list[32] or '--'  # 商務(wù)/特等座
          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 '--'  # 無座
          print(train_number,from_station_code,from_station_name,to_station_code,to_station_name,go_time,arrive_time,cost_time,special_class_seat,first_class_seat,second_class_seat,soft_sleep,
                hard_sleep,hard_seat,no_seat)

      from_station_name,to_station_name這兩個先這樣用,這里貼出來就是先測試看看數(shù)據(jù)是否抓取準確,然后再和前面的鏈接進行拼接,運行結(jié)果如下(部分):

      G108 AOH 上海 TIP 天津 07:22 12:45 05:23 5 有 有 -- -- -- --G1232 AOH 上海 TXP 天津 07:34 13:45 06:11 無 無 有 -- -- -- --G120 AOH 上海 TIP 天津 07:51 12:49 04:58 16 有 有 -- -- -- --G112 AOH 上海 TIP 天津 08:05 13:24 05:19 無 有 有 -- -- -- --G212 AOH 上海 TXP 天津 08:42 14:26 05:44 有 有 有 -- -- -- --G1258 AOH 上海 TXP 天津 09:08 14:34 05:26 -- 19 有 -- -- -- --

      可以看到數(shù)據(jù)吻合,這樣我們就完成了本篇文章的要求。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多