美文网首页
43.处理验证码并完成登陆

43.处理验证码并完成登陆

作者: M_小七 | 来源:发表于2020-08-27 15:54 被阅读0次

    处理验证码并完成登陆

    学习目标:
    1. 了解 使用打码平台处理验证图片
    2. 了解 实现12306登陆实现

    2.1 获取前置cookie

    根据抓包过程完成前置cookie的获取;使用requests.session()自动处理cookie;注意Referer

    # 12306.funk12306
    
    class Funk12306():
        def __init__(self, username, password):
            self.username = username
            self.password = password
            self.s = requests.session()
            self.s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
    
        def get_cookies(self):
            print('获取登录前的cookies')
    
            """以上都为获取cookies"""
    
            url = 'https://www.12306.cn/index/'
            self.s.get(url)
    
            url = 'https://kyfw.12306.cn/otn/login/conf'
            self.s.headers['Referer'] = 'https://kyfw.12306.cn/otn/resources/login.html'
            self.s.post(url)
    
            url = 'https://kyfw.12306.cn/otn/index12306/getLoginBanner'
            resp = self.s.get(url)
            print(resp.text)
    
            # 检查用户是否登录
            url = 'https://kyfw.12306.cn/passport/web/auth/uamtk-static'
            resp = self.s.post(url, data={'appid': 'otn'})
            print(resp.text)
    
            # 获取登录二维码
            url = 'https://kyfw.12306.cn/passport/web/create-qr64'
            resp = self.s.post(url, data={'appid': 'otn'})
            print(resp.text)
            uuid = json.loads(resp.text)['uuid']
    
            # 查询二维码状态
            url = 'https://kyfw.12306.cn/passport/web/checkqr'
            resp = self.s.post(url, data={'appid': 'otn', 'uuid': uuid})
            print(resp.text)
    

    2.2 获取图片验证码并处理

    • 2.2.1 获取图片验证码
    • 2.2.2 使用打码平台处理验证图片
    • 2.2.3 添加手动处理验证图片功能

    2.2.1 获取图片验证码

    图片保存到本地

    # 12306.funk12306.Funk12306.get_cookies
            # 获取验证码图片
            temp = str(time.time() * 1000)[:-5]  # 15421 76058 853
            url = 'https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&_={}'.format(temp)
            resp = self.s.get(url)
            print(resp.text)
            captcha_img_b64 = json.loads(resp.text)['image']
            captcha_img = base64.b64decode(captcha_img_b64)
            with open('./imgs/{}.png'.format(temp), 'wb') as f:
                f.write(captcha_img)
            
    

    2.2.2 使用打码平台处理验证图片

    使用 若快 打码 http://www.ruokuai.com,注册账号并充值

    # 12306_92.funk12306.utils.captcha
    
    # THE WINTER IS COMING! the old driver will be driving who was a man of the world!
    # -*- coding: utf-8 -*- python 3.6.7, create time is 18-11-29 下午6:18 GMT+8
    
    import hashlib
    import requests
    from datetime import datetime
    
    RUOUSER = 'xxx'
    RUOPASS = 'xxx'
    
    # 若快 12306打码 直接传入本地文件路径
    def getCode(img):
        url = "http://api.ruokuai.com/create.json"
        fileBytes = open(img, "rb").read()
        paramDict = {
            'username': RUOUSER,
            'password': RUOPASS,
            'typeid': 6113, # 专门用来识别12306图片验证的类型id
            'timeout': 90,
            'softid': 117157, # 推广用的
            'softkey': '70acaa1e477a4374a7736264a24b974b' # 推广用的
        }
        paramKeys = ['username',
                     'password',
                     'typeid',
                     'timeout',
                     'softid',
                     'softkey'
                     ]
        result = http_upload_image(url, paramKeys, paramDict, fileBytes)
        return result['Result']
    
    
    # 若快12306打码 上传图片
    def http_upload_image(url, paramKeys, paramDict, filebytes):
        timestr = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        boundary = '------------' + hashlib.md5(timestr.encode("utf8")).hexdigest().lower()
        boundarystr = '\r\n--%s\r\n' % (boundary)
    
        bs = b''
        for key in paramKeys:
            bs = bs + boundarystr.encode('ascii')
            param = "Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s" % (key, paramDict[key])
            # print param
            bs = bs + param.encode('utf8')
        bs = bs + boundarystr.encode('ascii')
    
        header = 'Content-Disposition: form-data; name=\"image\"; filename=\"%s\"\r\nContent-Type: image/gif\r\n\r\n' % ('sample')
        bs = bs + header.encode('utf8')
    
        bs = bs + filebytes
        tailer = '\r\n--%s--\r\n' % (boundary)
        bs = bs + tailer.encode('ascii')
    
        headers = {'Content-Type': 'multipart/form-data; boundary=%s' % boundary,
                   'Connection': 'Keep-Alive',
                   'Expect': '100-continue',
                   }
        response = requests.post(url, params='', data=bs, headers=headers)
        return response.json()
    
    
    if __name__ == '__main__':
        # 测试
        ret = getCode('../imgs/1544627949970.png')
        print(ret)
    

    2.2.3 添加手动处理验证图片功能

    用截图工具量取图片坐标(范围或单一坐标)

    # 12306.funk12306.Funk12306.get_cookies       
            
            # 选择打码方式并获取结果
            create_type = input(' 1 为手动打码 or 2 为收费平台自动打码,请选择:')
            if create_type == '1': # 手动打码
                answer_num = input('输入图片编号,从1开始:')
            elif create_type == '2': # 接入打码平台
                answer_num = getCode('./imgs/{}.png'.format(temp))  # 23
            else:
                raise Exception('输入错误! 1 为手动打码 or 2 为收费平台自动打码')
    
            # 改图片名字并获取点击坐标
            answer_dict = { '1': '37,46,',
                            '2': '110,46,',
                            '3': '181,46,',
                            '4': '253,46,',
                            '5': '37,116,',
                            '6': '110,116,',
                            '7': '181,116,',
                            '8': '253,116,' }
            os.rename('./imgs/{}.png'.format(temp),
                      './imgs/{}_{}.png'.format(temp, answer_num))
            answer = ''
            for i in answer_num:
                answer += answer_dict[i]
            answer = answer[:-1]
            print(answer)
            
            # 验证图片验证码
            url = 'https://kyfw.12306.cn/passport/captcha/captcha-check?answer={}&rand=sjrand&login_site=E&_={}'.format(
                answer, str(time.time() * 1000)[:-4])
            resp = self.s.get(url)
            print(json.loads(resp.text))
    

    2.3 完成登陆

    注意其中的跳转

    # 12306.funk12306.Funk12306.get_cookies  
    
            # 登录
            url = 'https://kyfw.12306.cn/passport/web/login'
            data = {'username': self.username,
                    'password': self.password,
                    'appid': 'otn',
                    'answer': answer}
            resp = self.s.post(url, data=data)
            print(resp.text)
            uamtk = json.loads(resp.text)['uamtk']
    
            # 进入登录后的页面 发生302跳转
            url = 'https://kyfw.12306.cn/otn/login/userLogin' # 302跳转
            self.s.get(url)
            url = 'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin'
            self.s.get(url)
    
            # 获取newapptk
            url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
            self.s.headers['Referer'] = 'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin'
            resp = self.s.post(url, data={'appid': 'otn'})
            print(json.loads(resp.text))
            newapptk = json.loads(resp.text)['newapptk']
    
            # 登录后验证
            url = 'https://kyfw.12306.cn/otn/uamauthclient'
            resp = self.s.post(url, data={'tk': newapptk})
            print(json.loads(resp.text))
    

    2.4 运行测试效果

    登陆效果.png

    小结

    1. 了解 使用打码平台处理验证图片
    2. 了解 实现12306登陆实现

    相关文章

      网友评论

          本文标题:43.处理验证码并完成登陆

          本文链接:https://www.haomeiwen.com/subject/mwserktx.html