zoukankan      html  css  js  c++  java
  • python3 requests 实现12306购票登录模块

    12306登录模块分析

    第一次写文章,记录一下学习的内容。今天先记录登录模块的分析和实现。

    在博客上看见一些大佬用的是splinter  webdriver写的12306购票过程。

    由于我之前学习了一阵子requests库,所以以下使用python3+requests实现12306购票。(当然也可以用python2 的urllib来实现)

    • 安装requests库
    pip3 install requests
    • 基本思路

    首先,我们可以使用谷歌浏览器的开发者模式,F12,来先分析一波登录12306的过程。(推荐大家一个好用的抓包工具Fiddler)

    • 打开登录界面,https://kyfw.12306.cn/otn/login/init
    • 先随意输入一个账号密码,再随意选验证码。(我们可以百度验证码类型,也可以自己尝试,可以知道12306的验证码是坐标型的验证码。)点击登录可以发现Network中多出一个xhr,点击查看(Headers  Preview  Response  Cookies  Timing都看看)可以发现Response返回的是:
    {"result_message":"验证码校验失败","result_code":"5"}
    answer: 91,53,107,109     为验证码坐标
    login_site: E      固定值
    rand: sjrand       固定值为验证码坐标
    login_site: E      固定值
    rand: sjrand       固定值

     

    • 可以使用qq截图的坐标来输入,从红色箭头开始向正确验证码拉动。
    • 输入正确的验证码后,查看Response为:
    {"result_message":"验证码校验成功","result_code":"4"}
    {"result_message":"密码输入错误。如果输错次数超过4次,用户将被锁定。","result_code":1}
    • 说明验证码验证通过,现在是账号密码问题,那么我们输入自己的正确的账号密码就可以完成登录了呗。

    代码:

    import requests
    from json import loads
    from user import username,password      #user.py   里面是自己正确的账号密码
    from urllib3 import disable_warnings
    from urllib3.exceptions import InsecureRequestWarning
    disable_warnings(InsecureRequestWarning)        #这三行作用是取消https警告
    locate={
        '1':'44,44,',
        '2':'114,44,',
        '3':'185,44,',
        '4':'254,44,',
        '5':'44,124,',                #8个图的坐标代号
        '6':'114,124,',
        '7':'185,124,',
        '8':'254,124,',
    }
    head={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36',
        'Referer': 'https://kyfw.12306.cn/otn/login/init',
    }                                         #加header 
    session=requests.Session()            #定义session,保持一个会话,验证码post和用户post保持同一个会话,之后的下单跨域保持登录
    session.verify=False                #取消验证SSL
    def login():
        resp1 = session.get(
                'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&',
                headers=head)
        with open('code.png','wb') as f:
            f.write(resp1.content)
        print('请输入验证码坐标代号:')
        code=input()
        write=code.split(',')
        codes=''
        for i in write:
            codes+=locate[i]
        data={
        'answer': codes,
        'login_site': 'E',
        'rand': 'sjrand'
        }
        resp=session.post('https://kyfw.12306.cn/passport/captcha/captcha-check',headers=head,data=data)
        html=loads(resp.content)
    
    
        if html['result_code']=='4':
            print('验证码校验成功!')
            login_url='https://kyfw.12306.cn/passport/web/login'
            user={
                'username': username,
                'password': password,
                'appid': 'otn'
            }
            resp2=session.post(login_url,headers=head,data=user)
            html=loads(resp2.content)
            print(resp2.text)
            if html['result_code'] == 0:
                print('登陆成功!')
            else:
                    print('登陆失败!')
        else:
    
    
            print('验证码校验失败,正在重新请求页面...')
            login()
        pass
    login()
    

    运行截图:

    到这里如果只是验证登录的话已经完成,要实现下单的话还没完,因为虽然显示登录成功,但是使用Fiddler抓包可以看到,在完成上述的登录后还需要进行两次验证,才能保证session验证登录成功,保持登录,之后下单过程才不会出错。

    两次验证URL分别为:

    https://kyfw.12306.cn/passport/web/auth/uamtk   post参数为 appid :otn
    https://kyfw.12306.cn/otn/uamauthclient    post参数为 第一次验证的Response的tk值

    session保持登录代码:

    import requests
    from json import loads
    from user import username,password
    from urllib3 import disable_warnings
    from urllib3.exceptions import InsecureRequestWarning
    disable_warnings(InsecureRequestWarning)
    locate={
        '1':'44,44,',
        '2':'114,44,',
        '3':'185,44,',
        '4':'254,44,',
        '5':'44,124,',
        '6':'114,124,',
        '7':'185,124,',
        '8':'254,124,',
    }
    head={
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36'
    }
    now_session=requests.Session()
    now_session.verify=False
    def login():
        print('-----------------验证码验证-----------------')
        resp1 = now_session.get(
            'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.8430851651301317',
            headers=head)
        with open('code.png','wb') as f:
            f.write(resp1.content)
        print('请输入验证码坐标代号:')
        code=input()
        write=code.split(',')
        codes=''
        for i in write:
            codes+=locate[i]
        data={
        'answer': codes,
        'login_site': 'E',
        'rand': 'sjrand'
        }
        resp=now_session.post('https://kyfw.12306.cn/passport/captcha/captcha-check',headers=head,data=data)
        html=loads(resp.content)
        if html['result_code']=='4':
            print('验证码校验成功!')
            print('-----------------登录中-----------------')
            login_url='https://kyfw.12306.cn/passport/web/login'
            user={
                'username': username,
                'password': password,
                'appid': 'otn'
            }
            resp2=now_session.post(login_url,headers=head,data=user)
            html=loads(resp2.content)
            print(html)
            if html['result_code']==0:
                print('登陆成功!')
                yzdata={
                    'appid':'otn'
                }
                tk_url='https://kyfw.12306.cn/passport/web/auth/uamtk'
                resp3=now_session.post(tk_url,data=yzdata,headers=head)
                print('-----------------第一次验证-----------------')
                print(resp3.text)
                login_message=resp3.json()['newapptk']
                print('loginMessage=',login_message)
                yz2data={
                    'tk':login_message
                }
                client_url='https://kyfw.12306.cn/otn/uamauthclient'
                resp4=now_session.post(client_url,data=yz2data,headers=head)
                print('-----------------第二次验证-----------------')
                print(resp4.text)
            else:
                print('登陆失败!')
        else:
            print('验证码校验失败,正在重新请求页面...')
            login()
        pass
    login()

    运行效果:

    备注:

    python2 urllib 的session由下面定义:

    cj = http.cookiejar.CookieJar()
    pro = urllib.request.HTTPCookieProcessor(cj)
    opener = urllib.request.build_opener(pro)
    urllib.request.install_opener(opener)


    写的很烂(见谅),有问题大家可以一起讨论。

  • 相关阅读:
    JavaFx在macOS下的文字渲染Bug
    Java多接口同名方法的冲突
    旧技术的惯性
    一点思考(1)
    slisp:编译到JVM平台上的lisp方言
    Arcee:又一个 Parser Generator 轮子
    使用Java实现一门简单的动态语言
    Hello World!
    [NOI2008]奥运物流
    [IOI2005]Riv河流
  • 原文地址:https://www.cnblogs.com/hecxx/p/11959863.html
Copyright © 2011-2022 走看看