python编写12306窗体抢票软件(二)

python编写12306窗体抢票软件(二)

本文这次介绍如何获取12306网站的验证码并登陆。

1 获取验证码

12306它是一个服务器,每次我们访问它都是以客户端的方式去向它索取信息。
建议用谷歌浏览器,按F12可以看到你发出去的请求和返回来的数据包,这样更好的理解这个过程。
上图:
在这里插入图片描述
选择Network,最左边就是打开这个网页所进行的每个过程,找到获取验证码的这一条,Headers,就能看到Request URL,这个就是你请求的链接,仔细看左边的流程,你会看到image,这个就是网站给你返回来的验证码图片,我们首先就是要获取到这个图片。
在这里插入图片描述

在这里插入图片描述
当你选择了验证码图片后,点击登录时,它会先检查你验证码对不对,看answer数据,这是两个坐标,整个验证码图片 有8个小图片,你只要点击的坐标范围是对的,就校验通过了。
所以我们需要输入的答案就是坐标值。

2.了解session

我们去访问一个网站,就是创建了一个session请求,后面我们所有进行的操作都是基于这个session去完成的,被访问的网站怎么知道你是第一次访问还是之前就访问过的呢,这通过cookies来完成,这个相当于服务器(也就是网站)给了你一把钥匙,之后你访问一直带着这个钥匙,他就知道你进行过什么操作了,这个也是之后非常重要的一步,关系到能否记住你的登录状态。

#创建一个session
req = requests.Session()
req.verify=False
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
    'Referer':'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin'
}

之后每次访问都用这个就自带cookies
里面这个url就是我们刚才F12我们看到的请求验证码那个链接,response就是返回的结果,里面带着验证码图片。我们把它存在本地,再通过窗体QLable这个也可以显示图片,把验证码显示出来。

    def get_img(self):
        #验证码
        response = req.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')
        with open('img.jpg', 'wb') as f:
            f.write(response.content)

这8个坐标对应8张图片的大概中心位置,
[‘35,35’, ‘105,35’, ‘175,35’, ‘245,35’,
‘35,105’, ‘105,105’, ‘175,105’, ‘245,105’]
然后我们去请求的链接中data中带上我们的答案,也就是坐标(12306登录是先验证你的验证码对不对,再去验证你的用户名和密码)如果返回值是4 我们再进行用户名和密码的请求

        Pic_addr = picnum.split(',')
        check_addr = ['35,35', '105,35', '175,35', '245,35', '35,105', '105,105', '175,105', '245,105']
        List = []
        for item in Pic_addr:
            List.append(check_addr[int(item)-1])
        Answer = ','.join(List)
        checkUrl = "https://kyfw.12306.cn/passport/captcha/captcha-check"
        data = {
            'login_site': 'E',  
            'rand': 'sjrand',  
            'answer': Answer  # 验证码对应的坐标
        }
        cont = req.post(url=checkUrl, data=data, headers=headers)
        dic = loads((cont.content).decode())
        code = dic['result_code']
        # 验证结果 
           4:成功 
           5:验证失败
           7:过期 
           8:没有带cookies
        if str(code) == '4':
            print('success')
            return True
        else:
            print('fail')
            return False

3 登录

loginUrl = “https://kyfw.12306.cn/passport/web/login
访问这个需要带上你的用户名和密码
代码:

    def login(self,username,password):
        userName = username
        pwd = password
        loginUrl = "https://kyfw.12306.cn/passport/web/login"
        data = {
            'username': userName,
            'password': pwd,
            'appid': 'otn'
        }
        response = req.post(url=loginUrl, data=data, headers=headers)

谨记:这里解析response它会返回登录成功,但这并不是真正的登录成功,还需进行下面两次请求才是真正登录上了,它会返回你的用户名。

    def login(self,username,password):
        userName = username
        pwd = password
        loginUrl = "https://kyfw.12306.cn/passport/web/login"
        data = {
            'username': userName,
            'password': pwd,
            'appid': 'otn'
        }
        response = req.post(url=loginUrl, data=data, headers=headers)
        data ={
            "appid": "otn"
        }
        Authurl = "https://kyfw.12306.cn/passport/web/auth/uamtk"
        response = req.post(url = Authurl , headers=headers, data=data)
        if response.status_code == 200:
            result = loads(response.text)
            #print(result.get("result_message"))
            newapptk = result.get("newapptk")
        data = {
            "tk": newapptk
        }
        clienturl = "https://kyfw.12306.cn/otn/uamauthclient"
        response = req.post(url =clienturl , headers=headers, data=data)
        if response.status_code == 200:
            print(response.text)
        dic = loads((response.content).decode("utf-8"))
        mes = dic['result_message']
        if mes == u'验证通过':
            self.Save_cookies()
            checkuser_url = 'https://kyfw.12306.cn/otn/login/checkUser'
            response = req.get(url=checkuser_url, headers=headers)
            response = response.json()['data']['flag']
            if response == True:
                print('验证通过')
                return True
            elif response == False:
                print('验证失败')
        else:
            return False

4.保存登录状态

如果上面都成功的话,就真的登陆上了。但是大家都知道平常我们用浏览器登录12306的时候,一段时间内是不会让你登录再登录的,这是因为我们在用浏览器访问的时候,cookies已经被保存在本地了,所以我们也可以这样做,来保存我们的登录状态。

    def Save_cookies(self):
        _cookies = req.cookies.get_dict()
        cookieStr = json.dumps(_cookies)
        with open('./cookies.txt', 'w') as f:
            f.write(cookieStr)
    def Get_cookies(self):
        try:
            with open('./cookies.txt', 'r') as f:
                 _cookies = json.load(f)
                 req.cookies = requests.utils.cookiejar_from_dict(_cookies)
        except:
            self.get_img()

这样就可以直接登录了,也就是我上文中界面有个直接登录按键的作用。

下次我会写获取12306车次信息,联系人等,如果写的多的话应该能写完~~请大家多多关注哈

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值