用Python攻破12306的最後一道防線,我看一遍就會了!
各位同學大家好,,好久沒跟大家帶來最新的技術文章了,最近有好幾個同學問我12306自動搶票能否實現,我就趁這兩天有時間用Python做了個12306自動搶票的項目,在這裡我來帶著大家一起來看看到底如何一步一步攻克萬惡的12306,嘻嘻~~
我們要做12306搶票而官方又沒有提供相應的介面(也不可能提供),那麼我們就只能通過自己尋找12306的數據包和買票流程來模擬瀏覽器行為實現自動化操作了,說直白一點就是爬蟲,接下來進入正題,前方高能,請系好好全帶~~
首先在買票前我們需要先確認是否有票,那麼進行正常的查票,打開12306查票網站
https://kyfw.12306.cn/otn/leftTicket/init
輸入出發地和目的地進行搜索
那麼一般在看到這個頁面的時候我們能想到的獲取車次及相關信息的方式是什麼呢?對於零基礎的同學而言第一時間就會想到在源代碼裡面找,但這裡事實上源代碼裡面根本沒有相關內容,因為該請求是採用的js中ajax非同步請求的方式動態載入的,並不包含在源代碼裡面,所以我們只能夠通過抓包的方式來查看瀏覽器與伺服器的數據交互情況,我用的是谷歌瀏覽器所以打開開發者工具的快捷鍵是F12
想要系統學習python和免費學習資料的 可以加裙 四七四五三四九五一
注意選中紅線框出來的那一個選項,此時只要是瀏覽器和伺服器發生數據交互都會在下面列表框顯示出來,我們再次點擊
查詢
按鈕
結果發現列表當中有了兩個請求,也就是說我們點擊
查詢
按鈕以後瀏覽器向伺服器發起了兩次請求,那麼我們來通過返回值分析下那個請求才是真正獲取到車次相關數據的請求,以便我們用Python來模擬瀏覽器操作
第一次請求:
很明顯第一次請求返回的值沒有我們需要的車次信息
第二次請求:
第二次請求裡面看到了很多數據,雖然我們暫時還沒看到車次信息,但是我們發現它有個特性,就是有個列表的值裡面有6個元素,而剛好我們搜索出來的從長沙到成都的車輛也是6條數據,所以這兩者肯定有一定關係,那麼我們先用Python來獲取到這些數據再進行下一步分析
# -*- coding: utf-8 -*-import urllib2import ssl
首先定義一個函數來獲取車次列表信息
從抓包數據中獲取到該請求的url:https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-07-10&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT
為了防止被12306檢測到屏蔽我們的請求那麼我們可以簡單的增加個頭信息來模擬瀏覽器的請求
req.add_header("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36")
其中的
ssl._create_default_https_context = ssl._create_unverified_context
是因為12306採用的是https協議,而ssl證書是它自己做的並沒有得到瀏覽器的認可,所以Python默認是不會請求不受信任的證書的網站的,我們可以通過這行代碼來關閉掉證書的驗證
那麼我們先來看看能不能正常獲取到我們想要的信息
事實證明我們的操作沒有問題,接下來先拿到包含有6條數據的這個列表再說
返回的數據是json格式,但是Python標準數據類型中沒有json這個類型,所以對於Python而言它就是個字元串,如果要非常方便的操作這個json我們就可以藉助Python中的json這個包來把json這個字元串變成dict類型,然後通過dict的鍵值對操作方法把列表取出來並進行返回
# -*- coding: utf-8 -*-import urllib2import sslimport json
最終返回的是一個list數據,我們先把這個數據for出來再看看每一條數據都有些什麼東西
for i in getList():
for出來之後我們先來看看第一條數據是什麼樣的:
其實我們稍微留一下就會發現裡面有包含
G1318,07:54,18:54,無
這樣的車次信息的,只不過看起來比較亂,但是他們都有一個特點,每個數據都是由
|
這個符號分開的,所以我們可以通過用
|
分割看看能發現什麼呢?
for i in getList(): for n in i.split("|"):
可以看到所有的值都列印出來了,我們再在前面加上一個序號就能清楚到看到每個序號所對應的值到底是什麼了,比如有輛火車硬座還剩3張票,軟卧還剩8張票,那我們就查看哪個序號對應的值是3哪個序號對應的值是8就搞清楚了哪個序號是代表什麼座次或者其他參數了
c = 0for i in getList(): for n in i.split("|"): print "[%s] %s" %(c,n)
到了這裡不知道同學們有沒有發現一個問題,就是我用的這個函數只能夠獲取到從
長沙
到
成都
的數據,而別人不一定是買這個方向的火車,所以我們還得搞清楚請求的url當中的出發站和到達站的值是怎麼來的
https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-07-10&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT
先找到出發站和到達站的參數分別是
leftTicketDTO.from_station=CDW
然而通過查找和分析我並沒有發現這兩個參數有規律,那麼也就是說這兩個值是在之前的請求裡面就已經獲取到了的,通過檢查網頁源代碼沒有找到,那麼又只能通過抓包的方式來找
在抓包過程中找到了一個包的返回值是附帶有各城市的代號的,url如下:
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9018
那麼我們把這裡面的城市數據複製出來單獨新建一個cons.py的文件保存起來
然後我們通過把參數做成通過輸入出發城市和到達城市就可以直接在這個數據裡面匹配到相應的城市代號,代碼如下:
station = {}for i in cons.station_names.split("@"): if i:
到這裡就已經能夠通過輸入
時間,城市
獲取相應的車次信息了
那麼我們再進行一些簡單的判斷,就能實現檢查相應的
時間,地點,車次
是否有餘票了
同時再結合
登錄,購票
等流程,通過自動判斷是否有票,如果無票就繼續刷新,直到有票之後自動登錄下單後通過簡訊或者電話等方式全自動聯繫購票人手機就可以了,如下圖
由於涉及到的知識點太多,僅僅用文字的方式很難表現的面面俱到,所以有時間的同學可以到我的課堂做客,現場直播講解更加的生動易懂!
想要系統學習python和免費學習資料的 可以加裙 四七四五三四九五一
※Python如何解析fasta格式,並儲存為字典?
※Python 如何編寫一個拼寫糾錯器?
※詳解基於樸素貝葉斯的情感分析及Python實現
※專為滲透測試人員設計的Python工具大合集
TAG:Python |
※一周ins瘋狂圈粉20w,微博超話閱讀+1億!他攻破你防線了嗎?
※Air Fear of God 1 掉出萬元鞋隊伍!滿天星失守 4000 元防線!
※GIF-阿根廷落後了!6人防線被打爆,4800萬大將目光獃滯
※5-4,世界盃俄羅斯險勝!這位1.86米老將撐起了球隊最後一道防線
※遼寧艦最後一道防線有多強?一旦全部啟動,2秒燒掉100萬
※反彈後續跌,2752成為下一道防線
※它是遼寧艦的最後一道防線,射擊1秒就要花費18萬
※遼寧號最後一道防線有多強?一旦全部啟動,2秒燒掉100萬
※美空軍一號有多安全?價值24架F35,三道防線,核爆炸都不怕
※美軍戰艦的最後一道防線 MK-38型25mm機炮系統
※皇馬玻璃渣防線13戰丟16球,隊長中途神秘離場,10vs11被狂轟5分鐘
※GIF-阿根廷陷絕境!6人防線被打爆,4800萬大將目光獃滯
※它是遼寧艦的最後一道防線,開機一秒鐘就花費18萬!
※lei了lei了,這道終極保護防線來了
※漲姿勢|遼寧艦、055和052D驅逐艦,為何都讓這導彈守最後防線?
※70年前,解放上海的最後一道防線這樣突破
※17元即可入手!《國土防線2:革命》Steam 2折促銷
※遼寧艦一旦開啟最後一道防線有多猛? 點射1秒需要花費50萬
※全球最廢物的四大防線:花了50億卻沒半點用,我國竟也上榜
※最沒用的4條軍事防線,一個花50億成笑柄,還有一個在中國