真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

終于搞定了回家車票

快要春節(jié)了,老板發(fā)話:'提前完成工作可以提前回家';于是老貓每天加班加點(diǎn)趕進(jìn)度,估計(jì)提前1周回家;正當(dāng)老貓沉浸在幸福之時(shí),老板過來關(guān)心問我:'老貓,車票買了嗎,買不到晚幾天走吧,那會(huì)好買';忽然有種被算計(jì)的感覺!!
終于搞定了回家車票
人無遠(yuǎn)慮必有近憂,車票是個(gè)大問題,老貓要買的車票這兩天放票;于是每天發(fā)動(dòng)同事幫我搶票,可是連續(xù)兩次都沒搶到;老貓有點(diǎn)慌了,買不到車票怎么辦?
終于搞定了回家車票

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序定制開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了淮北免費(fèi)建站歡迎大家使用!

那么多車票,為什么好幾個(gè)人搶連續(xù)兩天都搶不到;
終于搞定了回家車票
老貓分析其中可能存在原因,分析過程如下:

購票流程分析:

終于搞定了回家車票

1>老貓買的是比較緊張的車次,搶票人數(shù)遠(yuǎn)遠(yuǎn)大于出票數(shù)量;
2>每次搶票和網(wǎng)速,手速有一定關(guān)系;
3>雖然感覺每次手動(dòng)購票速度很快,但是購票人數(shù)多,手速快的也很多,對比而言也就不快了。

購票中存在影響因素:

老貓又仔細(xì)分析了網(wǎng)頁購票過程:

1>登錄,驗(yàn)證碼與密碼登錄;
2>刷票,選擇始發(fā)站,終點(diǎn)站,日期,車次;
3>出票后點(diǎn)擊預(yù)購;
4>等待排隊(duì),選擇乘車人;

理論上大家刷票過程都是一樣的,但是幾個(gè)因素會(huì)影響我們購票結(jié)果:

1>第一步登錄,這個(gè)沒有問題,老貓和大家都會(huì)提前登錄;
2>第二步:先看個(gè)示意圖:
終于搞定了回家車票
老貓?zhí)崆斑x擇好車次等信息,到出票時(shí)刻點(diǎn)擊刷票;但是網(wǎng)速與瀏覽器渲染頁面速度,可能會(huì)影響下一步操作;
3>刷票之后,如果出現(xiàn)購買車次,馬上點(diǎn)擊預(yù)購,這里會(huì)和自己手速有關(guān),幾百毫秒過去了,老貓可能已經(jīng)排在幾百人之后了;
4>點(diǎn)擊預(yù)購,出現(xiàn)下面頁面:
終于搞定了回家車票
這里考驗(yàn)手速:點(diǎn)擊購票人與訂單提交,然后憑天由命吧。

結(jié)合上面分析:搶熱點(diǎn)車次,真有點(diǎn)撞大運(yùn)的感覺。如何解決問題呢?

1>使用第三方軟件代購或者購買加油包;
2>拼車回家;

出去安全考慮,還是應(yīng)該選擇第一個(gè)方式。但是老貓有點(diǎn)好奇,為什么第三方軟件或者加油包能夠購買成功?老貓猜測可能原因:
終于搞定了回家車票

老貓認(rèn)為每個(gè)賬號就是一個(gè)購票者,這些賬號由腳本控制,到時(shí)間點(diǎn)開始搶票,腳本速度肯定要比人的速度快,所有購買成功幾率要大于認(rèn)為操作。以上部分構(gòu)成純屬瞎猜,如有雷同,純屬巧合。
這樣來看,老貓除了和幾萬個(gè)人競爭,還要和第三方軟件競爭,所以熱點(diǎn)車次的車票更難買到了。這樣大家也就理解為什么第三方軟件購買成功幾率更大。
為了驗(yàn)證這個(gè)猜測,老貓打算使用Pyhon腳本自動(dòng)登錄12306,說干就干。

1:登錄過程分析:

12306的驗(yàn)證碼是比較惡心的,每次弄得不清楚,還整一些不認(rèn)識的東西;老貓?jiān)?jīng)連續(xù)10次選擇錯(cuò)誤,最后系統(tǒng)警告我刷碼頻繁,最后只能讓人代買。
12306網(wǎng)頁版登錄過程分下面幾個(gè)部分:

1>輸入用戶名與密碼,如果不輸入,登錄提示錯(cuò)誤;
2>圖片驗(yàn)證;
2>賬號與密碼驗(yàn)證;

這里我們來看后兩個(gè)步驟:

1.1 驗(yàn)證碼分析

我們先借助瀏覽器分析登錄行為;
a)輸入用戶名與密碼,界面如下:
終于搞定了回家車票
b)點(diǎn)擊刷新,更新驗(yàn)證碼:
為了防止失效,看到效果,我們刷新驗(yàn)證碼;
請求地址:https://kyfw.12306.cn/passport/captcha/captcha-image64?
請求參數(shù):

{
    'login_site': 'E',
    'module': 'login',
    'rand': 'sjrand',
    '1546822674059':'',#當(dāng)前時(shí)間戳,
    'callback': 'jQuery19109060005139400158_1546821765087',#使用固定值
    '_': '1546821765097'#1546821765097,通過瀏覽器觀察:每次請求值加1
}

c)選擇驗(yàn)證碼并登陸(嘗試錯(cuò)誤選擇,觀察結(jié)果):
過程如下 :
終于搞定了回家車票
查看請求信息:
終于搞定了回家車票

驗(yàn)證失敗,應(yīng)答信息為:

jQuery19109060005139400158_1546821765087({"result_message":"驗(yàn)證碼校驗(yàn)失敗","result_code":"5"});

d)圖片驗(yàn)證分析:
圖片驗(yàn)證請求地址:https://kyfw.12306.cn/passport/captcha/captcha-check? ;
請求參數(shù):

{
    'callback': 'jQuery19109060005139400158_1546821765087',#與上一步請求驗(yàn)證圖片相同
    'answer': '111,52,109,96',#根據(jù)圖片選擇點(diǎn)擊位置
    'rand': 'sjrand',
    'login_site': 'E',
    '_': '1546821765102'#每次請求值加1,
}

e)如何選擇點(diǎn)擊位置?
有下面幾種方式:

1>機(jī)器學(xué)習(xí)圖片識別(設(shè)計(jì)內(nèi)容較多,準(zhǔn)確率不敢保證);
2>云打碼(老貓自己沒有折騰);
3>將圖片下載下來,自己選擇位置,手動(dòng)填入位置;

老貓實(shí)現(xiàn)方式:

1>觀察請求信息,坐標(biāo)應(yīng)該是正確圖片大概位置,
2>圖片信息:小圖長寬為70,
第一排坐標(biāo):(35,35),(105,35),(175,35),(245,35);
第二排坐標(biāo):(35,105),(105,105),(175,105),(245,105);
3>根據(jù)圖片提示,選擇對應(yīng)位置圖片,然后返回坐標(biāo);例如選擇0,1,返回值:
35,35,105,35

如果選擇成功,應(yīng)答消息中會(huì)有"驗(yàn)證碼校驗(yàn)成功"信息;
我們根據(jù)上面分析來使用代碼完成這一過程。

2:驗(yàn)證碼處理:

老貓將其過程分析下面幾步:

1>下載圖片,然后打開圖片查看;
2>輸入正確圖片位置,獲取坐標(biāo);
3>提交驗(yàn)證;

實(shí)現(xiàn)需要知識點(diǎn):

1>requests模塊,cookie管理;
2>Python基本知識點(diǎn)與面向?qū)ο缶幊蹋?/p>

實(shí)現(xiàn)思路:

1>通過瀏覽器獲取當(dāng)前callback值;
2>請求并保存驗(yàn)證碼;
3>手動(dòng)打開圖片,輸入正確位置,獲取坐標(biāo);
4>請求驗(yàn)證,如果驗(yàn)證失敗重復(fù)2~4步驟;

驗(yàn)證碼驗(yàn)證代碼實(shí)現(xiàn):

import re
import base64
import json
import requests
import time

class login12306:
    #初始化
    def __init__(self, callback, nums, headers):
        self.callback = callback
        self.nums = nums
        self.headers = headers
        self.s = requests.Session()
        self.fpath = './code.jpg'
    #發(fā)起請求
    def do_request(self, req_type='GET', url='',pdata=None, jdata=None):
        if req_type == 'POST':
            req = req = requests.Request(req_type, url, data=pdata, \
                                         json=jdata,headers=self.headers)
        else:
            req = requests.Request(req_type, url, params=pdata, \
                                   headers=self.headers)
        pre = self.s.prepare_request(req)
        try:
            resp = self.s.send(pre, timeout=3)
            return resp
        except:
            return None
    #獲取驗(yàn)證碼坐標(biāo)
    def gen_pointlist(self):
        #提示輸入位置
        indexs = input('input 1~8 : \n')
        width = 35
        points = []
        select = []
        #生成圖片對應(yīng)位置
        for i in range(0, 8):
            points.append([(i) % 4 * width * 2 + width, width * (i // 4 * 2) + width])
        #根據(jù)位置后去坐標(biāo)點(diǎn)
        [select.extend(points[int(index)-1]) for index in indexs]
        tmp = [str(val) for val in select]
        return ','.join(tmp)
    #下載驗(yàn)證碼
    def downimg(self):
        url = 'https://kyfw.12306.cn/passport/captcha/captcha-image64?'
        ts = str(int(time.time() * 1000))
        pdata = {
            'login_site': 'E',
            'module': 'login',
            'rand': 'sjrand',
            ts: '',
            'callback': self.callback,
            '_': str(self.nums)
        }
        req = self.do_request('GET', url, pdata=pdata)
        if not req:
            return
        m = re.search(r'\((.*)\)', req.text)
        text = m.group()[1:-1]
        jdata = json.loads(text)
        img = base64.b64decode(jdata['image'])
        with open(self.fpath, 'wb') as f:
            f.write(img)
        return True
    #獲取驗(yàn)證碼信息
    def get_qcinfo(self):
        #下載驗(yàn)證碼
        if self.downimg():
            #下載完成之后打開圖片,并輸入位置獲取坐標(biāo)
            indexs = self.gen_pointlist()
            return indexs
    #驗(yàn)證碼校驗(yàn)
    def qc_verify(self):
        indexs = self.get_qcinfo()
        if not indexs:
            return False
        self.nums += 1

        #驗(yàn)證碼輸入檢查
        url = 'https://kyfw.12306.cn/passport/captcha/captcha-check?'
        print(indexs)
        jdata = {
            'callback': self.callback,'answer': indexs,'rand': 'sjrand',
            'login_site': 'E','_': self.nums
        }
        req = self.do_request('GET', url, pdata=jdata)
        #輸入成功返回True
        if ('驗(yàn)證碼校驗(yàn)成功') in req.text:
            print('驗(yàn)證碼成功')
            self.indexs = indexs
            return True
        return False
    #用戶名與密碼登錄
    def user_login(self):
        pass
    #登錄接口
    def start_login(self):
        while True:
            if self.qc_verify():
                break
            time.sleep(2)
        self.user_login()

if __name__ == '__main__':
    callback = 'jQuery19109060005139400158_1546821765087',
    nums = 1546821765097
    hds = {'Accept-Language': 'zh-CN,zh;q=0.9',
               'Connection': 'keep-alive',
               'Host': 'kyfw.12306.cn',
               'Cache-Control': 'no-cache',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
               }
    obj =login12306(callback, nums, hds)
    obj.start_login()

運(yùn)行輸出結(jié)果如下:
終于搞定了回家車票

3:用戶登錄:

瀏覽器中,輸入正確驗(yàn)證碼,用戶名與密碼;點(diǎn)擊登錄,登錄過程如下圖:
終于搞定了回家車票

我們完善user_login方法,代碼如下:

    def user_login(self):
        url = 'https://kyfw.12306.cn/passport/web/login'
        jdata = {
            'username': 'myusername',#更換自己用戶名
            'password': 'mypwd',#更換成自己密碼
            'appid': 'otn',
            'answer': self.indexs,
        }

        req = self.do_request('POST', url, pdata=jdata)
        items = [
            {'url':'https://kyfw.12306.cn/otn/login/userLogin', 'f':'GET'},
            {'url':'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin','f':'GET'},
        ]
        for item in items:
            url = item.get('url')
            f = item.get('f')
            req = self.do_request(f, url)

        url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
        info = {'appid': 'otn'}
        req = self.do_request('POST', url, pdata=info)

        url = 'https://kyfw.12306.cn/otn/uamauthclient'
        jdata = req.json()
        info = {'tk': jdata['newapptk']}
        req = self.do_request('POST', url, pdata=info)

        req_items = [
            {'url':'https://kyfw.12306.cn/otn/login/userLogin','f':'GET'},
            {'url':'https://kyfw.12306.cn/otn/login/conf','f':'POST'},
            {'url':'https://kyfw.12306.cn/otn/index/initMy12306Api','f':'post'},

        ]
        for item in req_items:
            url = item.get('url')
            f = item.get('f')
            req = self.do_request(f, url)
        print(req.text)
        return req

再次運(yùn)行代碼結(jié)果如下:
終于搞定了回家車票
登錄成功了,我們可以提取應(yīng)答消息中的信息,判斷是否登錄成功。

對于用戶名密碼請求地址,我們可以不用關(guān)心具體作用,只需要記錄請求地址與參數(shù),有的數(shù)據(jù)可能需要在應(yīng)答中提取。基于這個(gè)基礎(chǔ),我們可以使用Python完成預(yù)定車次選擇,查找賬戶中聯(lián)系人,購票這一系列操作。
經(jīng)過分析,可以看到使用腳本操作,省去了頁面渲染與人為點(diǎn)擊這兩個(gè)操作,節(jié)省了時(shí)間,這樣訂單提交速度就比其他人快,購買成功幾率明顯增加。

但是老貓不打算使用,因?yàn)槭褂玫娜嗽蕉啵@種現(xiàn)象越猖獗;
終于搞定了回家車票
但是,老貓?jiān)趺椿乩霞夷兀坷县堃惶煨牟辉谘?,沒有一點(diǎn)工作狀態(tài)。老板看在心里也十分為我著急。

最終結(jié)果:

終于搞定了回家車票

最后廣告:

大家如果想學(xué)習(xí)Python及爬蟲技術(shù),可以查看下面兩個(gè)專欄:
Python爬蟲專欄地址:https://blog.51cto.com/cloumn/detail/17 ;
Python入門專欄地址:https://blog.51cto.com/cloumn/detail/34 ;


文章題目:終于搞定了回家車票
路徑分享:http://weahome.cn/article/piecds.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部