实例:基于selenium的12306模拟登陆
url:https://kyfw.12306.cn/otn/login/init
首页:
分析:
为了保证我们捕获的验证码和当次登录是匹配的,我们需要将当前selenium打开的登录页面中的验证码图片裁剪下来,识别任务由超级鹰完成,超级鹰的使用方法可以参考:https://blog.csdn.net/weixin_40576010/article/details/89196671
接着利用超级鹰返回的坐标值依次点击正确的验证码实现模拟登陆
注:一定要注意电脑的缩放,一般电脑缩放为125%,如果不想将缩放调为100%,在裁剪验证码时要将坐标值放大为1.25倍,在点击验证码时需要将超级鹰返回的坐标值缩小为0.8倍
程序代码:
import requests
from hashlib import md5
from selenium import webdriver
from selenium.webdriver import ActionChains
from time import sleep
from PIL import Image
#######超级鹰模板########
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
def transformImgCode(imgPath, imgType):
chaojiying = Chaojiying_Client('你的超级鹰账号', '你的超级鹰密码', '96001') # 用户中心>>软件ID 生成一个替换 96001
im = open(imgPath, 'rb').read()
return chaojiying.PostPic(im, imgType)['pic_str']
#######超级鹰模板########
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
bro.get('https://kyfw.12306.cn/otn/login/init')
sleep(2)
# 截图
bro.save_screenshot('main.png')
# 定位到验证码标签
img_tag = bro.find_element_by_xpath('//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
location = img_tag.location # 验证码左上角坐标
size = img_tag.size # 验证码的宽和高
# 计算验证码裁剪范围
rangle = (int(location['x'])*1.25, int(location['y'])*1.25, int(location['x'] + size['width'])*1.25, int(location['y'] + size['height'])*1.25)
# 根据裁剪范围对图片进行裁剪
img = Image.open('main.png')
frame = img.crop(rangle)
frame.save('code.png')
result = transformImgCode('code.png', 9004)
# 分离返回的x,y坐标值
all_list = []
if '|' in result:
list_1 = result.split('|')
for i in range(len(list_1)):
xy_list = []
x = int(list_1[i].split(',')[0])
y = int(list_1[i].split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
xy_list = []
x = int(result.split(',')[0])
y = int(result.split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
# 根据坐标值依次点击验证码
for xy in all_list:
x = xy[0]*0.8
y = xy[1]*0.8
ActionChains(bro).move_to_element_with_offset(img_tag, x, y).click().perform()
sleep(1)
print(all_list)
bro.find_element_by_id('username').send_keys('你的12306账号')
sleep(1)
bro.find_element_by_id('password').send_keys('你的12306密码')
sleep(1)
bro.find_element_by_id('loginSub').click()
sleep(2)
bro.quit()