处理验证码并完成登陆
学习目标:
- 了解 使用打码平台处理验证图片
- 了解 实现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小结
- 了解 使用打码平台处理验证图片
- 了解 实现12306登陆实现
网友评论