逢年過節(jié) 有一個(gè)神奇的網(wǎng)站 你一定不陌生 “12306” 是不是總搶不到票啊 是不是觀察著余票最新動(dòng)態(tài) 告訴你一個(gè)新技能 賊666 12306自動(dòng)搶票 前方高能,請(qǐng)系好好全帶~~ ... 首先在買票前我們需要先確認(rèn)是否有票,那么進(jìn)行正常的查票,打開12306查票網(wǎng)站https://kyfw.12306.cn/otn/leftTicket/init輸入出發(fā)地和目的地進(jìn)行搜索,。 那么一般在看到這個(gè)頁面的時(shí)候我們能想到的獲取車次及相關(guān)信息的方式是什么呢?對(duì)于零基礎(chǔ)的同學(xué)而言第一時(shí)間就會(huì)想到在源代碼里面找,但這里事實(shí)上源代碼里面根本沒有相關(guān)內(nèi)容,因?yàn)樵撜?qǐng)求是采用的js中ajax異步請(qǐng)求的方式動(dòng)態(tài)加載的,并不包含在源代碼里面,所以我們只能夠通過抓包的方式來查看瀏覽器與服務(wù)器的數(shù)據(jù)交互情況,我用的是谷歌瀏覽器所以打開開發(fā)者工具的快捷鍵是F12,。 注意選中紅線框出來的那一個(gè)選項(xiàng),此時(shí)只要是瀏覽器和服務(wù)器發(fā)生數(shù)據(jù)交互都會(huì)在下面列表框顯示出來,我們?cè)俅吸c(diǎn)擊查詢按鈕,。 結(jié)果發(fā)現(xiàn)列表當(dāng)中有了兩個(gè)請(qǐng)求,也就是說我們點(diǎn)擊查詢按鈕以后瀏覽器向服務(wù)器發(fā)起了兩次請(qǐng)求,那么我們來通過返回值分析下那個(gè)請(qǐng)求才是真正獲取到車次相關(guān)數(shù)據(jù)的請(qǐng)求,以便我們用Python來模擬瀏覽器操作,。 第一次請(qǐng)求: 很明顯第一次請(qǐng)求返回的值沒有我們需要的車次信息,。 第二次請(qǐng)求: 第二次請(qǐng)求里面看到了很多數(shù)據(jù),雖然我們暫時(shí)還沒看到車次信息,但是我們發(fā)現(xiàn)它有個(gè)特性,就是有個(gè)列表的值里面有6個(gè)元素,而剛好我們搜索出來的從長(zhǎng)沙到成都的車輛也是6條數(shù)據(jù),所以這兩者肯定有一定關(guān)系,那么我們先用Python來獲取到這些數(shù)據(jù)再進(jìn)行下一步分析。 # -*- coding: utf-8 -*- import urllib2 import ssl ssl._create_default_https_context = ssl._create_unverified_context def getList(): req = urllib2.Request('https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-07-10&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT') 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') html = urllib2.urlopen(req).read() return html print getList() 首先定義一個(gè)函數(shù)來獲取車次列表信息,。 從抓包數(shù)據(jù)中獲取到該請(qǐng)求的,。 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檢測(cè)到屏蔽我們的請(qǐng)求那么我們可以簡(jiǎn)單的增加個(gè)頭信息來模擬瀏覽器的請(qǐng)求。 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檢測(cè)到屏蔽我們的請(qǐng)求那么我們可以簡(jiǎn)單的增加個(gè)頭信息來模擬瀏覽器的請(qǐng)求,。 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 是因?yàn)?2306采用的是https協(xié)議,而ssl證書是它自己做的并沒有得到瀏覽器的認(rèn)可,所以Python默認(rèn)是不會(huì)請(qǐng)求不受信任的證書的網(wǎng)站的,我們可以通過這行代碼來關(guān)閉掉證書的驗(yàn)證,。 那么我們先來看看能不能正常獲取到我們想要的信息。 事實(shí)證明我們的操作沒有問題,接下來先拿到包含有6條數(shù)據(jù)的這個(gè)列表再說,。 返回的數(shù)據(jù)是json格式,但是Python標(biāo)準(zhǔn)數(shù)據(jù)類型中沒有json這個(gè)類型,所以對(duì)于Python而言它就是個(gè)字符串,如果要非常方便的操作這個(gè)json我們就可以借助Python中的json這個(gè)包來把json這個(gè)字符串變成dict類型,然后通過dict的鍵值對(duì)操作方法把列表取出來并進(jìn)行返回,。 # -*- coding: utf-8 -*- import urllib2 import ssl import json ssl._create_default_https_context = ssl._create_unverified_context def getList(): req = urllib2.Request('https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-07-10&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT') 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') html = urllib2.urlopen(req).read() dict = json.loads(html) result = dict['data']['result'] return result 最終返回的是一個(gè)list數(shù)據(jù),我們先把這個(gè)數(shù)據(jù)for出來再看看每一條數(shù)據(jù)都有些什么東西。 for i in getList(): print i for出來之后我們先來看看第一條數(shù)據(jù)是什么樣的: |預(yù)定|76000G131805|G1318|ICW|IZQ|ICW|CWQ|07:54|18:54|11:00|N|UHESFcaIDeX22Z0zWfqttDuZXJFuWPdIa148i6TNk5spIqfp|20170710|3|W2|01|16|0|0|||||||||||無|無|無||O0M090|OM9 其實(shí)我們稍微留一下就會(huì)發(fā)現(xiàn)里面有包含G1318,07:54,18:54,無這樣的車次信息的,只不過看起來比較亂,但是他們都有一個(gè)特點(diǎn),每個(gè)數(shù)據(jù)都是由|這個(gè)符號(hào)分開的,所以我們可以通過用|分割看看能發(fā)現(xiàn)什么呢? for i in getList(): for n in i.split('|'): print n break 可以看到所有的值都打印出來了,我們?cè)僭谇懊婕由弦粋€(gè)序號(hào)就能清楚到看到每個(gè)序號(hào)所對(duì)應(yīng)的值到底是什么了,比如有輛火車硬座還剩3張票,軟臥還剩8張票,那我們就查看哪個(gè)序號(hào)對(duì)應(yīng)的值是3哪個(gè)序號(hào)對(duì)應(yīng)的值是8就搞清楚了哪個(gè)序號(hào)是代表什么座次或者其他參數(shù)了,。 c = 0 for i in getList(): for n in i.split('|'): print '[%s] %s' %(c,n) c += 1 c = 0 break #索引3=車次 #索引8=出發(fā)時(shí)間 #索引9=到達(dá)時(shí)間 到了這里不知道同學(xué)們有沒有發(fā)現(xiàn)一個(gè)問題,就是我用的這個(gè)函數(shù)只能夠獲取到從長(zhǎng)沙到成都的數(shù)據(jù),而別人不一定是買這個(gè)方向的火車,所以我們還得搞清楚請(qǐng)求的url當(dāng)中的出發(fā)站和到達(dá)站的值是怎么來的,? https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-07-10&leftTicketDTO.from_station=CDW&leftTicketDTO.to_station=CSQ&purpose_codes=ADULT 先找到出發(fā)站和到達(dá)站的參數(shù)分別是:
然而通過查找和分析我并沒有發(fā)現(xiàn)這兩個(gè)參數(shù)有規(guī)律,那么也就是說這兩個(gè)值是在之前的請(qǐng)求里面就已經(jīng)獲取到了的,通過檢查網(wǎng)頁源代碼沒有找到,那么又只能通過抓包的方式來找。 在抓包過程中找到了一個(gè)包的返回值是附帶有各城市的代號(hào)的,url如下: https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9018 那么我們把這里面的城市數(shù)據(jù)復(fù)制出來單獨(dú)新建一個(gè)cons.py的文件保存起來,。 然后我們通過把參數(shù)做成通過輸入出發(fā)城市和到達(dá)城市就可以直接在這個(gè)數(shù)據(jù)里面匹配到相應(yīng)的城市代號(hào),代碼如下: station = {} for i in cons.station_names.split('@'): if i: tmp = i.split('|') station[tmp[1]] = tmp[2] #print station train_date = raw_input('請(qǐng)輸入出發(fā)時(shí)間') from_station = station[raw_input('請(qǐng)輸入出發(fā)城市')] to_station = station[raw_input('請(qǐng)輸入到達(dá)城市')] 到這里就已經(jīng)能夠通過輸入時(shí)間,城市獲取相應(yīng)的車次信息了 那么我們?cè)龠M(jìn)行一些簡(jiǎn)單的判斷,就能實(shí)現(xiàn)檢查相應(yīng)的時(shí)間,地點(diǎn),車次是否有余票了,。同時(shí)再結(jié)合登錄,購票等流程,通過自動(dòng)判斷是否有票,如果無票就繼續(xù)刷新,直到有票之后自動(dòng)登錄下單后通過短信或者電話等方式全自動(dòng)聯(lián)系購票人手機(jī)就可以了。 看完了,,屌屌的 你學(xué)到了嗎 知識(shí)點(diǎn)太多 文字看得太累 我們貼心送了一份大禮 只送給關(guān)注【設(shè)計(jì)癖】的你 “福利” 現(xiàn)場(chǎng)直播課 課后錄制視頻 隨堂代碼免費(fèi)贈(zèng)送 雙擊666 反正我報(bào)名了 掃描下方的二維碼 掃描二維碼加入專屬QQ學(xué)習(xí)群 或者直接通過搜索QQ號(hào): 204795506 在學(xué)習(xí)Python的過程中很多時(shí)候?qū)τ赼jax異步加載和驗(yàn)證碼的爬蟲束手無策,其實(shí)只要了解了原理就容易解決了,一個(gè)爬蟲高手一定是一個(gè)web開發(fā)高手,因?yàn)榕老x和反爬是相輔相成的,能夠完成12306網(wǎng)站的自動(dòng)購票基本能搞定互聯(lián)網(wǎng)80%以上的爬蟲. 1:Python爬蟲包的使用 2:文本處理,提取指定信息,過濾無用信息 3:爬蟲開發(fā)思想和原則,爬取深度定義 4:ajax異步的處理 5:項(xiàng)目完整業(yè)務(wù)邏輯實(shí)現(xiàn) 聽眾收益
騰訊課堂Python研究院高級(jí)講師 強(qiáng)子老師 8年P(guān)ython開發(fā)經(jīng)驗(yàn),,幫助國(guó)內(nèi)的創(chuàng)業(yè)公司做 Web 開發(fā)、爬蟲,、數(shù)據(jù)可視化,。Python 開發(fā)及開源愛好者,vim 控,,熟悉 Django, redis, docker 等,。 先后在多個(gè)項(xiàng)目中成功的實(shí)施數(shù)據(jù)可視化,熟悉 Matlab / iGraph / d3 / neo4j 等可視化工具,。 |
|