python編程實現12306的一個小爬蟲實例
本文思路主要來源于實驗樓的教程,但是一些具體的一些細節(jié)是我自己發(fā)現的,比如哪里獲得站點對應的3位英文編號,怎么獲得這個查詢的url
本文用到的庫主要有requests(獲取url的內容),prettytable(讓文本輸出美觀),argparse(命令行參數解析)
關于這些庫怎么使用,可以參見我之前的博文
1、首先打開12306余票查詢的界面
https://kyfw.12306.cn/otn/lcxxcx/init
我們想要的信息當然就是在輸入了始發(fā)站、終點站和日期之后各車次的時間和車票余量,那么我們嘗試在始發(fā)站使用檢查元素,觀察一下它是怎么上傳始發(fā)站的信息的,那么我們不妨隨便輸入出發(fā)地、目的地和信息,使用抓包工具來看看它是怎么發(fā)包的(使用瀏覽器也可以,因為我們只需要查看包的內容,不需要更改包)
2、

在chrome的network中我們可以查看到我們點擊之后瀏覽器發(fā)送的所有包(關于http包的知識不熟悉的同學,可以看看《圖解http》這本書)

點擊查詢之后我們馬上就會注意到以query開頭的這個包,顯然這就是一個查詢指令,我們看看這個包的url
'https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=2016-10-04&from_station=BJP&to_station=XKS'
然后我們看看它的response

仔細觀察就能發(fā)現它其實是一串json格式的字符串(要非常有經驗。。。。)
3、經過以上這些過程,我們大致就能知道我們需要做的是什么了,我們只需要更改url中的data,fromstaion,tostaion后面的內容,然后用requests獲得response,然后解析這一串json字符就行了。
但是我們會發(fā)現,日期還好說,對于fromstation和tostaion的代碼,我們該怎么辦呢?
4、有兩種可能,一中可能是這些文件在服務器上,每回改變站點網頁都會從服務器請求這個站點的代碼,還有一種可能是這個已經下載到本地了,如何判斷呢?我們不妨改變一下始發(fā)站,然后用抓包軟件(或者瀏覽器)觀察我們的瀏覽器是否向12306發(fā)送了包

把北京改成了上海,但是我們發(fā)現瀏覽器并沒有發(fā)送包
這樣我們基本可以肯定這個車站編號信息是存在本地了(已經從服務器下載下來)
5、我們這時候,就需要分析html來發(fā)現這個編號信息到底儲存在了那里
我們試著檢查一下出發(fā)地附近的html標簽,在‘熱門'上面點擊檢查,我們很容易發(fā)現這個標簽上面帶了一個onclick方法

我們發(fā)現這個onclick方法指向了一個js文件,并且名字是‘Stationfor12306',基本我們可以確定這個js文件就是我們需要的站點信息文件了。
6、我們嘗試在這個html(12306余票查詢界面)里面搜一下stationfor,我們馬上就能發(fā)現,它就在<head>標簽的<script>元素里,并且指向了一個url

進入這個url看看,我們馬上就發(fā)現站點信息已經被我們找到啦(注意這是一個相對URL,絕對url需要在前面補上https://kyfw.12306.cn/)

關于怎么獲取三位數的車站代碼,用正則,字符串查詢都是可以的啦,由于這里是固定的3位車站代碼,我就用簡單的字符串查詢來提取這個代碼了。
7、剩下的工作,基本就是代碼實現了,關于具體怎么實現,我把我的代碼貼在下面了。
#coding=utf-8
import requests
import argparse
import datetime
import re
from prettytable import PrettyTable
now = datetime.datetime.now()
tomorrow = now+datetime.timedelta(days=1)
tomorrow = tomorrow.strftime('%Y-%m-%d')
print tomorrow
argument = argparse.ArgumentParser()
argument.add_argument('--fromcity','-f',default='hangzhoudong')
argument.add_argument('--tocity','-t',default='xiamen')
argument.add_argument('--date','-d',default=tomorrow)
# argument.add_argument('-d',action='store_true')
args =argument.parse_args()
from_station = args.fromcity
to_station = args.tocity
Date = args.date
stationlist_url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js'
r = requests.get(stationlist_url, verify=False)
stationlist = r.content
ToStation = ''
FromStation = ''
placea = stationlist.find(from_station)
placeb = stationlist.find(to_station)
for i in range(-4,-1):
FromStation += stationlist[placea+i]
for i in range(-4,-1):
ToStation += stationlist[placeb+i]
query_url='https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate='+Date+'&from_station='+FromStation+'&to_station='+ToStation
r = requests.get(query_url,verify=False)
with open('json.txt','w') as fp:
fp.write(str(r.json()))
if 'datas' in r.json()["data"]:
rj = r.json()["data"]["datas"]
pt = PrettyTable()
header = '車次 車站 到站時間 時長 一等座 二等座 軟臥 硬臥 硬座 無座'.split()
pt._set_field_names(header)
for x in rj:
ptrow = []
ptrow.append(x["station_train_code"])
ptrow.append('\n'.join([x["from_station_name"],x["to_station_name"]]))
ptrow.append('\n'.join([x["start_time"], x["arrive_time"]]))
ptrow.append(x["lishi"].replace(':','h')+'m')
ptrow.append(x['zy_num'])
ptrow.append(x['ze_num'])
ptrow.append(x['rw_num'])
ptrow.append(x['yw_num'])
ptrow.append(x['yz_num'])
ptrow.append(x['wz_num'])
pt.add_row(ptrow)
print pt
else :
print '這兩個站點沒有直達列車'
總結
以上就是本文關于python編程實現12306的一個小爬蟲實例的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關文章
Python實現微信自動回復信息的功能(根據不同信息回復對應的信息)
這篇文章主要介紹了Python實現微信自動回復信息的功能(根據不同信息回復對應的信息),我們使用的第三方包是UIAutomation,結合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-09-09
python GUI庫圖形界面開發(fā)之PyQt5切換按鈕控件QPushButton詳細使用方法與實例
這篇文章主要介紹了python GUI庫圖形界面開發(fā)之PyQt5切換按鈕控件QPushButton詳細使用方法與實例,需要的朋友可以參考下2020-02-02

