python的requests库爬虫登录12306铁路网

本文使用python的第三方库requests实现12306网的登录以及验证码的提交功能。

本次操作是手动输入验证码,并不是自动识别提交验证码,因为自动识别提交验证码需要用到图像处理与模式识别,还没学到这方面的知识。

实现步骤:

1.创建会话session,如果单单使用requests.get()和post()等等方法是无法实现登录的。因为直接使用requests.get()方法执行后,没有保存cookie下来,下次访问服务器就无法获取验证码图片和其他任何东西。学过web的同学应该懂得。

2.使用session进入登录首页

然后打开浏览器,进入12306网登录页面,打开浏览器的审查元素

3.获取验证码图片,并存到本地文件

4.手动输入验证码

因为12306网的验证码是点击的,不是输入字母或者数字的

解决方法是:

发现上图中红色框中的数据是提交给服务器的验证码数据,这个数据是验证码图片中8张图中正确的验证码图片的像素的坐标组成

我们建立一个字典存储8张图片所在的像素坐标,以及一个函数获取正确的验证图片像素坐标组成

怎么知道每一个图片的像素坐标呢?

你可以使用电脑的画图软件打开之前保存下来的验证码图片,一般y轴坐标都是要减掉30的,因为图片上面的‘请输入下图中所有。。。。’是不包括的,像下面(40,69)最后应是(40,39)或者(40,40),在附近就行。

然后手动输入验证码的格式是输入第几张,用逗号隔开。上面的例子就是第二个和第四个图片,所以输入:2,4

这样通过定义的函数就可以获取正确的验证码格式。然后通过提交表单校验验证码。

4.校验验证码

根据返回的response,提取结果代码,判断是否校验成功。

可以添加print(captcha_check_response.text)打印返回数据,得到成功与失败的结果代码result_code,这样就可以设计下面的代码。下面登录验证用户名与密码同样。

5.验证码校验成功后,开始提交用户名与密码,在浏览器审查元素中找到提交用户名与密码的url

6.一般其他的网站登录的实现到上面就结束了,但是12306网的登录还没,我们还需获取到token才能确定登录成功

在浏览器中使用网页登录,第一步在审查元素中找到uamtk

第二步找到uamauthclient,一般都是在uamtk下面

代码如下:

进行到这里就登录成功了。

全部实现代码:

import requests
#1.创建会话session
session = requests.Session()
headers = {'User-':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'}
session.headers.update(headers)
#2.进入12306登录页面
url = 'https://kyfw.12306.cn/otn/login/init'
response = session.get(url)
#3.获取验证码图片,并保存到本地文件
captcha_url = 'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.8006430591776557'
captcha_response = session.get(captcha_url)
with open('captcha.jpg','wb') as f:
    f.write(captcha_response.content)
#4.验证码提交验证
#定义一个字典变量来存验证码图片的像素坐标
map = {
    '1':'35,40',
    '2':'107,45',
    '3':'175,43',
    '4':'254,43',
    '5':'37,115',
    '6':'110,118',
    '7':'177,117',
    '8':'255,119'
}
#定义一个函数来获取验证码的提交格式
def make_answer(numpict):
    num = numpict.split(',')
    answer = ''
    for i in range(len(num)):
        answer += map[num[i]] + ','
    return answer[:-1]

#手动输入验证码
captcha_answer = make_answer(input('请输入正确的验证码:'))
captcha_check_url = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
form_data = {
    'answer':captcha_answer,  #验证码答案,填写正确图片的像素坐标
    'login_site':'E',
    'rand':'sjrand'
}
#校验验证码
captcha_check_response = session.post(captcha_check_url,data = form_data)
result_code = captcha_check_response.json()["result_code"] #获取返回的结果代码判断是否校验成功
if result_code != '4':
    if result_code == '7':
        print("验证码已经过期")
    else:
        print('验证码校验失败')
else:
    #验证码校验成功,执行用户名密码提交登录
    login_url = 'https://kyfw.12306.cn/passport/web/login'
    username = 'xxxxxxxxxx'
    password = 'xxxxxx'
    form_data = {
        'username': username,
        'password': password,
        'appid':'otn'
    }
    login_response = session.post(login_url,data = form_data)
    if login_response.json()["result_code"] == 0:
        #登录成功,获取权限token
        uamtk_url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
        form_data = {'appid':'otn'}
        uamtk_response = session.post(uamtk_url,data = form_data)
        if uamtk_response.json()["result_code"] == 0:
            uamauthclient_url = 'https://kyfw.12306.cn/otn/uamauthclient'
            form_data = {'tk':uamtk_response.json()["newapptk"]}
            uamauthclient_response = session.post(uamauthclient_url,data = form_data)
            print(uamauthclient_response.json())
        else:
            print('权限token获取失败')
        print('登录成功')
    else:
        print('登录失败,用户名或者密码错误')

exit()

猜你喜欢

转载自blog.csdn.net/Thanours/article/details/83575581