滑块验证码登录
简介
现在很多网站的登录,都采用了拖动图片滑块的验证码方式来进行验证登录,比如哔哩哔哩和京东等。在使用爬虫等自动化程序时,如何通过滑块验证,就成了需要解决的问题。
这里通过大名鼎鼎的ddddocr图片识别库,和模拟浏览器操作的selenium库来实现
Selenium简介
安装浏览器driver
首先你需要下载一个浏览器的driver,Chrome的下载地址如下,注意参考你的Chrome版本,下载对应的exe文件,然后运行即可。
下载地址:Chrome for Testing availability (googlechromelabs.github.io)
运行后出现下图,放着就行了:
pip安装Selenium包
pip install selenium
Selenium的基本使用如下:该例子打开百度首页,并搜索python
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
# 通过元素ID获取元素
kw_input = browser.find_element(By.ID, 'kw')
# 模拟用户输入行为
kw_input.send_keys('Python')
# 通过CSS选择器获取元素
su_button = browser.find_element(By.CSS_SELECTOR, '#su')
# 模拟用户点击行为
su_button.click()
input("请输入回车结束")
ddddocr简介
ddddorc库是一个比较好用的图片识别库,目前支持滑块、文字验证码、点选验证码的识别
官方地址:https://github.com/sml2h3/ddddocr
我们用到的语法如下(事实上该例子就在官方文档首页:
slide = ddddocr.DdddOcr(det=False, ocr=False)
# 这是滑块图片
with open('target.jpg', 'rb') as f:
target_bytes = f.read()
# 这是背景大图片
with open('background.jpg', 'rb') as f:
background_bytes = f.read()
# 返回的是坐标关系
res = slide.slide_match(target_bytes, background_bytes, simple_target=True)
print(res)
返回值如下,四个值分别表示左上角和右下角的,水平和垂直距离:
{'target_y': 0, 'target': [113, 61, 163, 111]}
实战举例
本次我们来模拟登录京东,因为刚好是一个很容易获取到的滑块验证码网站~
用Selenium获取对应元素进行登录
我们分别获取用户名和密码框,输入账号和密码,然后获取登录框点击登录
def sel_main():
browser = webdriver.Chrome()
# browser.maximize_window()
browser.get('https://passport.jd.com/uc/login')
# 点击账户密码登录
up_btn = browser.find_element(By.ID, 'pwd-login')
up_btn.click()
# 通过元素ID获取用户名和密码框
username_input = browser.find_element(By.ID, 'loginname')
pw_input = browser.find_element(By.ID, 'nloginpwd')
# 模拟输入
username_input.send_keys('1xxxxxx93')
pw_input.send_keys('111222333')
# 选取登录按钮
submit_btn = browser.find_element(By.ID, 'loginsubmit')
# su_button = browser.find_element(By.CSS_SELECTOR, '#su')
# 模拟用户点击行为
submit_btn.click()
此时会跳出滑块验证码的图片,我们分别获取他们,将图片下载到本地:
# 获取验证码图片背景大图
captcha = browser.find_element(By.XPATH, '//div[@class="JDJRV-bigimg"]/img')
captcha_img = captcha.get_attribute('src')
captcha_size = (captcha.size['width'], captcha.size['height'])
handle_img(captcha_img, 'bg', captcha_size, 'bg_sized')
# 获取滑块小图
wrap = browser.find_element(By.XPATH, '//div[@class="JDJRV-smallimg"]/img')
wrap_img = wrap.get_attribute('src')
wrap_size = (wrap.size['width'], wrap.size['height'])
handle_img(wrap_img, 'sm', wrap_size, 'sm_sized')
对验证码图片进行处理
下载到的图片是图片的原始大小,这就会产生一个问题。在浏览器中进行拖动时,实际要拖动的是图片在浏览器中实际渲染出来的大小。这两者中间是存在误差的,所以通过以下方法对图片进行处理,让它变成和浏览器中是一样大的:
def handle_img(img_src: str, name: str, size: tuple, name_sized: str):
"""
对下载的验证码图片进行处理
:param img_src: 原图片编码
:param name: 保存名称
:param size: 调整的大小,元组(width, height)
:param name_sized: 调整后的图片名
:return: 无
"""
s_img = img_src.replace('data:image/png;base64,', '')
img_byte = base64.b64decode(s_img)
with open(f"../images/{name}.png", "wb") as f:
f.write(img_byte)
img = Image.open(f"../images/{name}.png")
res_img = img.resize(size)
res_img.save(f"../images/{name_sized}.png")
计算拖动距离
验证码图片和滑块都获取到了,通过以下方法,来计算拖动距离
def get_distance(tg_img, bg_img):
"""
获取滑动距离
:param bg_img: 底层大图片
:param tg_img: 滑块小图片
:return: 返回距离
"""
# 读取图片
with open(f"../images/{tg_img}.png", "rb") as f:
tg = f.read()
with open(f"../images/{bg_img}.png", "rb") as f:
bg = f.read()
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
# 目标图无多余背景,需要加入simple_target参数
res = det.slide_match(tg, bg, simple_target=True)
return res['target'][0]
模拟进行拖动
滑块的拖动显然不能直接拖过去,那样速度太快太准确,一下子就被发现不是人类啦。所以我们只能尽可能模拟手动操作,用以下方法进行拖动:
def do_moves(browser, distance, btn):
"""
加速度滑动法,计算生成轨迹然后滑动
:param browser: 浏览器对象
:param distance: 滑动距离
:param btn: 滑动对象
:return:无
"""
# 生成运动轨迹
track = []
current = 0
mid = distance * 4 / 5
t = 0.2
v = 1
while current < distance:
if current < mid:
a = 4
else:
a = -3
v0 = v
v = v0 + a*t
move = v0*t + 0.5*a*t*t
current += move
track.append(round(move))
ActionChains(browser).click_and_hold(btn).perform()
for x in track:
ActionChains(browser).move_by_offset(xoffset=x, yoffset=random.randint(-5, 5)).perform()
# 重置滑动值,否则多次滑动会超出范围
ActionChains(browser).reset_actions()
time.sleep(0.5)
ActionChains(browser).release(on_element=btn).perform()
拖动不一定成功,所以用一个try的循环,如果失败就再来一次
保存cookie
登录成功后用如下语句保存cookie
cookies = browser.get_cookies()
with open("cookies.json", "w") as c:
c.write(f"{cookies}")
使用cookie
既然已经模拟登录成功了,那么要如何使用cookie呢?
以下例子访问一个需要登录的页面,来使用cookie
def use_cookies():
# 我的订单页面,需要登录才能访问
test_url = "https://order.jd.com/center/list.action"
# 从本地读取cookie文件,
with open("cookies.json", 'r') as c:
cookies = eval(c.read())
cookie = [item["name"] + "=" + item["value"] for item in cookies]
# 拼接成字符串
cookie_str = '; '.join(item for item in cookie)
print(cookie_str)
# 将cookie放入header中
header = {
'cookie': cookie_str,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
html = requests.get(test_url, headers=header)
print(html.text)
完整代码请参考如下链接:
https://github.com/h-kayotin/kayotin_toolbox/blob/master/sel/sel_JD_login.py文章来源:https://www.toymoban.com/news/detail-815072.html
参考资料:https://github.com/zjy6622/python-/blob/master/selenium京东模拟登陆.py文章来源地址https://www.toymoban.com/news/detail-815072.html
到了这里,关于用Selenium实现滑块验证码登录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!