12306自動搶票軟件代碼實現

昨天我發的是抓取的12306數據包,然後分析了一下,今天按照昨天的分析 用代碼實現了,如果有需要的同學們可以看一下

實現的功能有,登錄,驗證碼識別,自動查票,有餘票點擊預定, 差了最後一步提交訂單。同學們可以自己研究一下。


import requests
import time
import dmpt
import re
import random
from copyheaders import headers_raw_to_dict

DEFAULT_HEADERS={
'Host':'kyfw.12306.cn',
'Connection':'keep-alive',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Referer':'https://kyfw.12306.cn/otn/index/init',
'Accept-Language':'zh-CN,zh;q=0.9',
}
def get_random():
    return str(random.random()) #生產一個18位的隨機數
def get_13_time():  #一個十三位的時間戳
    return str(int(time.time()*1000))
class CN12306(object):
    def __init__(self):
        self.chufa='2018-02-03'
        self.s=requests.session()
        self.s.verify = False   # 忽略https 證書驗證
    def get_init(self):  #請求了一個首頁
        url='https://kyfw.12306.cn/otn/login/init'
        r=self.s.get(url)
        print('首頁獲取成功,狀態碼:',r)

    def get_newpasscode(self):  #這個頁面不知道是幹啥的,但是12306 請求了,咱們爲了模仿的像一點也去請求
        url='https://kyfw.12306.cn/otn/resources/js/newpasscode/captcha_js.js?_={}'.format(get_13_time())
        r=self.s.get(url)
        print('newpasscode獲取成功,狀態碼:',r)

    def get_auth_code(self):  #獲取驗證碼
        url='https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{}'.format(get_random())
        r=self.s.get(url)
        with open('auth_code.png', 'wb') as auth:
            auth.write(r.content)
            auth.flush()
            auth.close()
        return str(r) == '<Response [200]>'

    def analysis_auth_code(self):  # 調用打碼平臺,返回驗證碼座標
        dmt = dmpt.DamatuApi("打碼平臺帳號", "打碼平臺密碼")
        analysis_auth = dmt.decode('auth_code.png', 287)  # 上傳打碼
        analysis_auth = re.sub('\|', ',', analysis_auth)
        li = analysis_auth.split(',')
        for i in range(len(li)):
            if i % 2 == 0:
                pass
            else:
                li[i] = str(int(li[i]) - 30)
        analysis_auth = str(li)
        analysis_auth = re.sub("'", '', analysis_auth)
        analysis_auth = re.sub("\]", '', analysis_auth)
        analysis_auth = re.sub("\[", '', analysis_auth)
        analysis_auth = re.sub(" ", '', analysis_auth)
        print('驗證碼座標', analysis_auth)
        self.analysis_auth= analysis_auth  # 驗證碼座標

    def auth_auth_code(self): #驗證驗證碼是否正確提交方式post
        url='https://kyfw.12306.cn/passport/captcha/captcha-check'
        data={
            'answer':self.analysis_auth ,
            'login_site':'E',
            'rand':'sjrand',
        }
        r=self.s.post(url=url,data=data)
        print(r.text)
        if r.text == '''{"result_message":"驗證碼校驗成功","result_code":"4"}''': #驗證碼校驗成功
            return True
        else:  #如果驗證碼校驗失敗
            print('驗證碼錯誤,刷新驗證碼,重新提交')
            if self.get_auth_code():   #獲取驗證碼
                self.analysis_auth_code() #調用打碼平臺
                self.auth_auth_code()  #重新校驗驗證碼

    def login(self):
        url='https://kyfw.12306.cn/passport/web/login'
        data={
        'username' : '12306帳號',
        'password' : '12306密碼',
        'appid' : 'otn',
        }
        r=self.s.post(url=url,data=data)
        self.uamtk=r.json()["uamtk"]

        print(r.text)

    def userLogin(self):
        url='https://kyfw.12306.cn/otn/login/userLogin'
        r=self.s.post(url=url)
        # print(r.text)
    def getjs(self):   #不知道是幹啥的,但是也提交吧
        url='https://kyfw.12306.cn/otn/HttpZF/GetJS'
        r=self.s.get(url)
    def post_uamtk(self):
        url='https://kyfw.12306.cn/passport/web/auth/uamtk'
        data={ 'appid':'otn'}
        r=self.s.post(url=url,data=data,allow_redirects=False)
        self.newapptk=r.json()["newapptk"]
        r.encoding='utf-8'
        print(r.text)
    def post_uamauthclient(self):
        url='https://kyfw.12306.cn/otn/uamauthclient'
        data={
            'tk':self.newapptk
        }
        r=self.s.post(url=url,data=data)
        self.apptk = r.json()["apptk"]
        r.encoding='utf-8'
        print(r.text)
    def get_userLogin(self):
        url='https://kyfw.12306.cn/otn/login/userLogin'
        r=self.s.get(url)
        r.encoding='utf-8'
        # print(r.text)
    def get_leftTicket(self):
        url='https://kyfw.12306.cn/otn/leftTicket/init'
        r=self.s.get(url)
        r.encoding='utf-8'
        # print(r.text)
    def get_GetJS(self):
        url='https://kyfw.12306.cn/otn/HttpZF/GetJS'
        self.s.get(url)

    def get_qufzjql(self):
        url = 'https://kyfw.12306.cn/otn/dynamicJs/qufzjql'
        self.s.get(url)

    def get_queryZ(self):
        url='https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes={}'.format(self.chufa,'BJP','TBP','ADULT')
        r=self.s.get(url)
        r.encoding='utf-8'
        # print(r.text)
        cheliang=r.json()["data"]["result"]
        for i in cheliang:
            dandulist=str(i).split('|')
            if len(str(dandulist[0]))>=100:
                self.secretStr=dandulist[0]
                # secretStr = str(x[0])
                車次=str(dandulist[3])
                出發時間=str(dandulist[8])
                到達時間 = str(dandulist[9])
                歷時=str(dandulist[10])
                軟臥 = str(dandulist[23])
                硬臥=str(dandulist[28])
                print(i)
                print('可預訂車次列表,','車次:',車次,'出發時間:', 出發時間,'到達時間:', 到達時間,'歷時:', 歷時,'軟臥剩餘:  ',軟臥,'  硬臥剩餘:  ',硬臥)
                if (軟臥 != '' and  軟臥 != '0'  and 軟臥 != '無' and 軟臥 != '空') or (硬臥 != '' and  硬臥 != '0'  and 硬臥 != '無' and 硬臥 != '空'):
                    #執行下單操作
                    self.post_submitOrderRequest()
                    self.post_initDc()
                    self.post_getPassengerDTOs()
                    return False

            print('*****************************************************')
        return True


    # 點擊預定下單
    def post_submitOrderRequest(self):
        url='https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
        data={
            'secretStr':self.secretStr,
            'train_date':self.chufa,  #出發時間
            'back_train_date':self.chufa ,#返回時間
            'tour_flag':'dc',
            'purpose_codes':'ADULT',
            'query_from_station_name':'北京',
            'query_to_station_name':'天津北',
            'undefined':''
              }
        r=self.s.post(url=url,data=data)
        print(r.text)
    def post_initDc(self):
        url='https://kyfw.12306.cn/otn/confirmPassenger/initDc'
        r=self.s.post(url)
        # r.text
        self.REPEAT_SUBMIT_TOKEN=re.findall("globalRepeatSubmitToken = '(.*?)';",r.text)[0]
    def post_getPassengerDTOs(self): #獲取乘客信息
        url='https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
        data={
            'REPEAT_SUBMIT_TOKEN':self.REPEAT_SUBMIT_TOKEN,
            '_json_att':''
        }
        r=self.s.post(url=url,data=data)
        r.encoding='utf-8'
        print(r.text)

if __name__ == '__main__':
    print(get_random())
    cn=CN12306()
    cn.get_init()
    cn.get_newpasscode()
    if cn.get_auth_code():
        #如果驗證碼獲取成功,就調用打碼平臺
        print('驗證碼獲取成功')
        print('正在調用打碼平臺...')
        cn.analysis_auth_code()
        if cn.auth_auth_code():  #驗證驗證碼是否正確
            cn.login()
            cn.userLogin()
            cn.getjs()
            cn.post_uamtk()
            cn.post_uamauthclient()
            cn.get_userLogin()
            cn.get_leftTicket()
            cn.get_GetJS()
            cn.get_qufzjql()

            while cn.get_queryZ():
                time.sleep(30)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章