一、滑动验证码概述
滑动验证码也叫行为验证码,比较流行的一种验证码,通过用户的操作行为来完成验证。滑动验证码的原理就是使用机器学习中的深度学习技术,根据一些特征来区分是否为正常用户。
通过记录用户的滑动速度,还有每一小段时间的瞬时速度,用户鼠标点击情况,以及滑动后的匹配程度来识别。而且,不是说滑动
二、滑动验证码常见类型
● 常规的滑动验证码
● 极验验证码:字符串类型 和 canvas两种类型
三、滑动验证码处理方案
1. 常规滑动验证码的处理
目标网址:滑块页面
一般来说我们与页面的交互可以使用 Webelement 的方法来进行点击等操作。但是,有时候我们需要一些更复杂的动作,类似于拖动,双击,长按等等。这时候就需要用到我们的 Action Chains (动作链)了。
常规的滑动验证码直接滑动就可以,但是某些大平台网站会检测selenium,一旦被检测到就会提示错误,并且用selenium打开的网页自己手动滑都不会成功,如果出现了这样的情况,可以用本地浏览器启动,因为本地浏览器是肯定可以正常滑动的。
详情参考:https://blog.csdn.net/weixin_45081575/article/details/126585575
2. 极验验证码处理
说到滑动验证码,一定一定要提某验,虽然说市面上关于滑动验证码的产品有很多,但是某验的地位就像 10 年前脑白金在保健品市场的地位一样,业界标杆啊。
它越牛逼,市场上用它做防护的网站也越多,像国家企业信用信息公示系统、B 站、京东等等。像某验的解决方案也有很多,不过原理大同小异。
● 通过代码来模拟验证码滑动主要有3个步骤:
- 获取验证码图片,包含缺口图,滑块图,完整图
- 计算缺口位置,滑块位置,滑块要滑动的距离
- 通过鼠标自动化模块模拟操作
1. 字符串图片类型处理
● 目标网址:https://union.jd.com/login
● 注意事项:滑动验证码会涉及到滑动操作,需要和页面交互,因此选择用selenium操作
获取验证码图片
在目标网址中输入用户名和密码点击登录后,就会弹出滑动验证码。通过在Elements元素面板中查看验证码的标签可以看出其验证码加载的形式是字符串形式的验证码。
● 下载验证码
这种类型的验证码图片有一个特点,在网页中的加载图片的形式不是普遍的链接形式,而是以字符串形式加载图片的。这种形式里面的数据分为两部分,由英文逗号分隔,逗号左边是图片的声明信息,包含图片的后缀格式和字符串的编码类型;逗号右边的所有数据是字符串形式的图片数据。处理这种字符串图片类型的验证码可以通过以下方法:
- 使用selenium获取字符串形式的图片数据,也就是英文逗号右边的所有数据。咱们需要获取两张图片,一张是带缺口的验证码的图片, 一张是单独的缺口图片。有这个两张图就可以使用ddddocr识别缺口的距离。至于是哪个标签对应哪一张图,大家在Elements中鼠标移动到图片的字符串数据就可以看到图片样式,如下所示:
2. 使用base64模块将字符串图片数据转化成二进制图片类型,将验证码图片保存,部分代码如下所示:
3. 计算实际缩放比例
当我们使用selenium解析到字符串图片数据,并且转化成二进制保存图片文件的时候,操作的是原图。但是浏览器页面在前端排版布局的时候有时候原图太大或者太小就会缩放图片,然后填充到页面。因此我们需要提前计算出缩放比例,在后续用ddddocr计算缺口距离以后, 实际距离值也要根据缩放比例计算才是真实浏览器要滑动的距离。
原图的图像大小我们下载图片后即可查看,浏览器页面的图像大小可以在Elements右侧边栏的盒子模型中查看,如下所示:
缩放比例计算部分代码如下所示:
4. 以下代码是下载验证码,并且计算缩放比例的代码:
def get_image():
"""下载图片到本地, 计算缩放比例返回"""
time.sleep(1)
target = driver.find_element(By.CSS_SELECTOR, '.JDJRV-bigimg img')
template = driver.find_element(By.CSS_SELECTOR, '.JDJRV-smallimgimg')
"""保存背景图"""
bg_base64 = target.get_attribute('src').split(',')[-1] # 背景图
bg_img_name = 'output_bg.png'
bg_content = base64.b64decode(bg_base64)
with open(bg_img_name, mode='wb') as f:
f.write(bg_content)
"""保存滑块图"""
slide_base64 = template.get_attribute('src').split(',')[-1] # 滑块图
slide_img_name = 'output_slide.png'
slide_content = base64.b64decode(slide_base64)
with open(slide_img_name, mode='wb') as f:
f.write(slide_content)
img_long = target.rect['width']
local_img = Image.open(bg_img_name)
size_loc = local_img.size # 图片长宽
scaling = round(img_long