前言

有小伙伴们私信反馈说,在web自动化的过程中,经常会被登录的验证码给卡住,不知道如何去通过验证码的验证。今天专门给大家来聊聊验证码的问题,一般的情况下遇到验证码我们可以都可以找开发去帮忙解决,关闭验证码!我们自己有没有办法来处理这些验证码的问题呢?答案当然是有的,常见的验证码一般分为两类,一类是图文验证码,一类是滑块验证码!


关于图文识别的验证码,之前已经出了相关的识别解决方案,今天就不做过多的介绍了,有兴趣的小伙伴可以 领取配套的视频资料 。今天我们主要来聊聊滑动验证码如何去识别破解。

→→→先领资料,再学习←←←

一、滑动验证破解思路

关于滑动验证码破解的思路大体上来讲就是以下两个步骤:

  1. 获取滑块滑动的距离

  2. 模拟拖动滑块,通过验证。

看起来是很难,实际一点都不简单。 但是获取滑块滑动的距离,大多数小伙伴没有思路,不知道怎么去获取。其实要获取下来也不难,关于这种滑动的验证码,滑块和缺口背景都是分别是一张独立的图片,我们可以把这两张图片,下载下来借助于图像识别的技术,去识别缺口在背景图中的位置,然后减去滑块当前所在位置,就可以得出需要滑动的距离。这个时候很多小伙伴会想图像识别技术我不会啊,不会没有关系,后面会给到大家一个封装好的滑块识别模块,只要你传入滑块和缺口背景图的元素节点就能计算出滑块的缺口位置。

二、案例讲解

话不多说,我们先来看一个案例,这边用到了一个我自己封装的滑动距离识别的模块slideVerfication,有需要的小伙伴可以文末名片处获取。登录案例实现步骤如下:

  1. 创建一个driver对象,访问qq登录页面
  2. 输入账号密码
  3. 点击登录
  4. 模拟滑动验证

三、代码实现

import timefrom selenium import webdriverfrom slideVerfication import SlideVerificationCode​# 1、创建一个driver对象,访问qq登录页面browser = webdriver.Chrome()browser.get("https://qzone.qq.com/")# 2、输入账号密码# 2.0 点击切换到登录的iframebrowser.switch_to.frame('login_frame')# 2.1 点击账号密码登录browser.find_element_by_id('switcher_plogin').click()# 2.2定位账号输入框,输入账号browser.find_element_by_id("u").send_keys("123292678")# 2.3定位密码输入输入密码browser.find_element_by_id("p").send_keys("PYTHON01")# 3、点击登录browser.find_element_by_id('login_button').click()time.sleep(3)# 4、模拟滑动验证# 4.1切换到滑动验证码的iframe中tcaptcha = browser.find_element_by_id("tcaptcha_iframe")browser.switch_to.frame(tcaptcha)# 4.2 获取滑动相关的元素# 选择拖动滑块的节点slide_element = browser.find_element_by_id('tcaptcha_drag_thumb')# 获取滑块图片的节点slideBlock_ele = browser.find_element_by_id('slideBlock')# 获取缺口背景图片节点slideBg = browser.find_element_by_id('slideBg')# 4.3计算滑动距离sc = SlideVerificationCode(save_image=True)distance = sc.get_element_slide_distance(slideBlock_ele,slideBg)# 滑动距离误差校正,滑动距离*图片在网页上显示的缩放比-滑块相对的初始位置distance = distance*(280/680) - 22print("校正后的滑动距离",distance)# 4.4、进行滑动sc.slide_verification(browser,slide_element,distance=100)


关于滑动验证码的识别问题就这样解决了,那么接下来给大家来讲讲封装的slideVerfication这个模块的识别原理,其实关于这个模块图像识别,也是借助了第三方的图像处理模块来进行识别的,python中有很多现成的用来处理图片的库,这边我使用的是opencv-python来进行识别的。slideVerfication模块上面用到的两个方法的部分参考代码如下:

def get_element_slide_distance(self, slider_ele, background_ele, correct=0):

根据传入滑块,和背景的节点,计算滑块的距离该方法只能计算 滑块和背景图都是一张完整图片的场景,如果背景图是通过多张小图拼接起来的背景图,该方法不适用,请使用get_image_slide_distance这个方法

:param slider_ele: 滑块图片的节点:type slider_ele: WebElement:param background_ele: 背景图的节点:type background_ele:WebElement:param correct:滑块缺口截图的修正值,默认为0,调试截图是否正确的情况下才会用:type: int:return: 背景图缺口位置的X轴坐标位置(缺口图片左边界位置)
# 获取验证码的图片slider_url = slider_ele.get_attribute("src")background_url = background_ele.get_attribute("src")# 下载验证码背景图,滑动图片slider = "slider.jpg"background = "background.jpg"self.onload_save_img(slider_url, slider)self.onload_save_img(background_url, background)# 读取进行色度图片,转换为numpy中的数组类型数据,slider_pic = cv2.imread(slider, 0)background_pic = cv2.imread(background, 0)# 获取缺口图数组的形状 -->缺口图的宽和高width, height = slider_pic.shape[::-1]# 将处理之后的图片另存slider01 = "slider01.jpg"background_01 = "background01.jpg"cv2.imwrite(background_01, background_pic)cv2.imwrite(slider01, slider_pic)# 读取另存的滑块图slider_pic = cv2.imread(slider01)# 进行色彩转换slider_pic = cv2.cvtColor(slider_pic, cv2.COLOR_BGR2GRAY)# 获取色差的绝对值slider_pic = abs(255 - slider_pic)# 保存图片cv2.imwrite(slider01, slider_pic)# 读取滑块slider_pic = cv2.imread(slider01)# 读取背景图background_pic = cv2.imread(background_01)# 比较两张图的重叠区域result = cv2.matchTemplate(slider_pic, background_pic, cv2.TM_CCOEFF_NORMED)# 获取图片的缺口位置top, left = np.unravel_index(result.argmax(), result.shape)# 背景图中的图片缺口坐标位置print("当前滑块的缺口位置:", (left, top, left + width, top + height))return leftdef slide_verification(self, driver, slide_element, distance):

滑动滑块进行验证

:param driver: driver对象:type driver:webdriver.Chrome:param slide_element: 滑块的元组:type slider_ele: WebElement:param distance: 滑动的距离:type: int:return:
# 获取滑动前页面的url地址start_url = driver.current_urlprint("需要滑动的距离为:", distance)# 根据滑动距离生成滑动轨迹locus = self.get_slide_locus(distance)print("生成的滑动轨迹为:{},轨迹的距离之和为{}".format(locus, distance))# 按下鼠标左键ActionChains(driver).click_and_hold(slide_element).perform()time.sleep(0.5)# 遍历轨迹进行滑动for loc in locus:time.sleep(0.01)ActionChains(driver).move_by_offset(loc, random.randint(-5, 5)).perform()ActionChains(driver).context_click(slide_element)# 释放鼠标ActionChains(driver).release(on_element=slide_element).perform()

学习资源推荐

除了上述分享,如果你也喜欢编程,想通过学习Python获取更高薪资,这里给大家分享一份Python学习资料。

朋友们如果有需要的话,可以V扫描下方二维码联系领取

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

因篇幅有限,仅展示部分资料,添加上方即可获取

一、Python学习路线

二、Python基础学习
1. 开发工具

2. 学习笔记

3. 学习视频

三、Python小白必备手册

四、数据分析全套资源

五、Python面试集锦
1. 面试资料

2. 简历模板

朋友们如果有需要的话,可以V扫描下方二维码联系领取

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

因篇幅有限,仅展示部分资料,添加上方即可获取