← 返回文章列表

Selenium自动化测试遇到滑块验证码?三种破解思路实战解析

滑块验证码是Web自动化测试中的常见障碍。本文通过三个实际案例,讲解如何用Selenium配合ActionChains处理简单滑块、拼图滑块以及Canvas绘制的滑块验证码,并介绍更高效的第三方识别方案。

Selenium自动化测试遇到滑块验证码?三种破解思路实战解析

做过爬虫或者自动化测试的朋友,肯定被各种滑块验证码折磨过。明明代码写得好好的,结果卡在验证码这一关出不去,真是让人头疼。今天咱们就聊聊怎么用Selenium来应对这些滑块验证码,从最简单的直线滑动,到需要拼图的复杂场景,我都给大家掰开了揉碎了讲。

最基础的横向滑块:一把梭就完事

这种验证码最简单,就是让你按住滑块往右拖到底。实现起来也不复杂,核心就是用ActionChains的drag_and_drop_by_offset方法。这个方法接收三个参数:要拖动的元素、X轴偏移量、Y轴偏移量。因为是横向滑动,所以Y轴给0就行。

关键在于怎么知道要滑多远。最直接的办法就是手动测一下,用浏览器开发者工具量一量滑块轨道的宽度。比如某个网站的滑块轨道是338像素,那代码里就写338。当然这种硬编码的方式不够灵活,但对于固定的网站来说够用了。

actionChains = ActionChains(browser)
slide_btn = browser.find_element_by_id('sliderblock')
actionChains.drag_and_drop_by_offset(slide_btn, 338, 0).perform()

这段代码先创建一个ActionChains对象,然后定位到滑块元素,最后执行拖拽操作。perform()方法是真正触发动作的关键,别忘了调用。

拼图滑块:计算位置差是核心

这类验证码稍微复杂一点,页面上会出现一个缺口和一个滑块,你需要把滑块拖到缺口位置。好在这种验证码的缺口和滑块位置都是通过CSS的left属性控制的,我们可以直接读取这两个值,算出差值就知道要滑多远了。

具体实现时,先点击滑块触发验证码显示,然后用get_attribute方法获取style属性,再用正则表达式提取出left的数值。两个left值相减,得到的就是滑动距离。这里有个小坑,提取出来的值可能带空格,记得用strip()清理一下。

white_btn_style = browser.find_element_by_id('missblock').get_attribute('style')
grey_img_style = browser.find_element_by_id('targetblock').get_attribute('style')
white_offset_px = re.search(r'left: (.*?)px;', white_btn_style).group(1)
grey_offset_px = re.search(r'left: (.*?)px;', grey_img_style).group(1)
slider_px = float(grey_offset_px.strip()) - float(white_offset_px.strip())

算出距离后,还是用drag_and_drop_by_offset方法执行滑动。这种方法的优点是不需要图像识别,纯粹靠DOM操作就能搞定,速度快而且稳定。

Canvas绘制的滑块:图像对比来帮忙

最麻烦的是用Canvas绘制缺口的验证码。因为Canvas是动态绘制的,没有DOM元素可以读取,前面那套方法就不管用了。这时候就得上图像处理技术,通过对比有缺口和没缺口的两张图,找出差异位置。

实现思路是这样的:先截取一张完整背景图,然后点击滑块让缺口出现,用JavaScript把滑块隐藏掉(不然会挡住缺口),再截取一张带缺口的图。接着用PIL库的ImageChops.difference方法对比两张图的差异,getbbox()会返回差异区域的坐标,这个坐标的X值就是我们要的滑动距离。

before_img = Image.open('before.png').convert('RGB')
after_img = Image.open('after.png').convert('RGB')
different_place = ImageChops.difference(before_img, after_img)
diff_position = different_place.getbbox()
actionChains.drag_and_drop_by_offset(slide_btn, diff_position[0]-10, 0).perform()

这里有个技术细节要注意:打开图片时必须用convert('RGB')转成RGB模式,不然ImageChops.difference可能返回None。另外,实际滑动时可能需要微调距离,比如减去10个像素,这个要根据具体网站调试。

实战中的痛点和解决方案

说实话,上面这些方法在实验环境里跑得挺好,但真正用到生产环境就会发现各种问题。比如有些验证码会检测鼠标轨迹,你直接匀速滑过去肯定被识别成机器人。还有些验证码会动态调整难度,今天能过明天就不行了。更别提极验、易盾这些专业的验证码服务商,人家的反爬技术可不是吃素的。

如果你的项目对验证码识别有稳定性要求,或者需要处理点选、文字点选、九宫格这些更复杂的验证码类型,自己写代码真的很费劲。这时候用专业的识别服务会省心很多。像www.ttocr.com这样的平台,专门针对极验和易盾做了优化,支持滑块、点选、无感等全类型验证码,提供API接口可以直接对接到你的代码里。

对接也很简单,就是把验证码图片发给API,它返回识别结果,你再用Selenium执行对应操作就行。这样既不用研究复杂的图像识别算法,也不用担心验证码升级导致代码失效,把精力放在业务逻辑上不是更香吗?

写在最后

验证码这东西,说白了就是网站和自动化工具之间的攻防战。简单的滑块你可以自己写代码搞定,但遇到复杂的验证码,还是要借助专业工具。毕竟时间成本也是成本,与其在验证码上死磕,不如找个靠谱的识别服务,让项目快速上线才是正道。