← 返回文章列表

滑块为什么总差一点?用Python与Selenium弄懂极验拼图验证

滑块验证既检查拼图位置,也结合交互行为与会话状态判断结果。通过页面定位、图像比较、坐标换算和结果检查,可以理解自动化测试中的常见问题;业务接入还需关注接口适配、异常处理与验证码服务的能力边界。

一、拼图对上了,验证为何还会失败

做过浏览器自动化的人,大多遇到过这样的场景:登录按钮已经点开,账号密码也填好了,页面却弹出一张拼图,要求把滑块拖到缺口。肉眼看起来很简单,交给程序就容易出问题。差几像素可能失败,位置看着对了也可能失败,因为滑块验证检查的不只是最后停在哪里。

极验这类验证通常会把图像任务、交互过程和当前会话关联起来。前端负责展示图片、收集操作,服务端再结合提交的数据判断结果。具体检查哪些信息,要看产品版本与接入方式,不能拿某个旧页面的表现当成固定规则。理解这个前提,才能解释为什么同一段脚本在不同环境下表现不同。

从技术上拆开看,传统拼图分析可以分成几个环节:找到缺口图,取得可用于比较的完整图,估算缺口位置,把图片坐标换算成页面上的移动距离,再检查验证结果。每一步都有自己的误差来源。图片识别负责回答“缺口在哪”,浏览器操作负责回答“控件怎么动”,两者之间还隔着坐标转换。

早期教程常拿B站登录页面演示这种流程,但登录入口、页面结构和验证版本都会变化。如今照抄旧元素选择器,可能连弹窗都找不到。更合适的学习环境是自己有权限操作的测试页面:先把图像、坐标和事件处理弄明白,再对照实际接入文档分析页面,避免把历史演示误当成通用方案。

二、先看清页面,再让Selenium动手

Selenium能控制真实浏览器,完成点击、输入、截图和鼠标操作。它的优势是能够观察页面实际呈现的状态,适合处理依赖脚本渲染的界面。不过,浏览器打开成功不等于验证码已经就绪,弹窗出现也不等于图片已经加载完成。自动化流程需要根据页面状态推进,不能只靠固定等待时间碰运气。

定位元素时,可以从登录入口、验证码容器、图片区域和滑块控件逐层检查。优先选择相对稳定的属性,少依赖层层嵌套的位置关系。有些组件放在iframe里,需要切换上下文;还有些会在刷新后重新创建节点,旧的元素引用随之失效。遇到定位报错,先确认当前页面结构,再判断是不是选择器的问题。

显式等待适合处理这些变化。例如等待弹窗可见、滑块能够交互,或者图片尺寸不再为零。等待条件最好对应业务状态,而不是统一睡几秒。网络快时固定休眠浪费时间,网络慢时又不够用。对于会重新渲染的组件,应在操作前重新定位关键元素,并保留失败截图,方便复盘当时的界面。

浏览器窗口大小、页面缩放和设备像素比也要记录。同一张图片,在截图中可能占六百像素,在页面上却只有三百个CSS像素宽。若直接把截图里的距离交给鼠标,拖动量就会翻倍。固定测试窗口、明确缩放比例,并在识别与操作之间保持布局稳定,往往比反复调整距离更有效。

三、找缺口之前,先把两张图对齐

传统方法依赖两张对应图片:一张带缺口,一张是完整背景。对齐后逐列比较像素,缺口区域通常会形成明显差异。但这个前提并非总能满足。有的组件通过canvas绘制,有的图片经过切片重组,还有的根本不会向页面提供完整背景。取得的是同一轮任务、同一尺寸的图像,才有比较意义。

从整页截图裁出验证码区域时,需要确认截图坐标与元素位置使用同一套尺度。页面滚动、浏览器缩放和高分屏都可能让裁剪框偏移。能直接截取元素时,通常更容易减少无关区域。若选择读取图像资源,还要检查它是否已经解码成完整画面,不能把未经还原的切片当作背景进行差分。

图像差分的思路很直白:比较同一位置的颜色,差异超过阈值就记下来,再观察这些差异在水平方向如何分布。不要看到第一个不同的像素就认定那里是缺口。压缩噪声、阴影、边框和拼图块本身都可能产生差异。把一整列的信息累加,再寻找连续变化区域,通常比单点判断更稳。

from PIL import Image, ImageChops
full = Image.open('full.png').convert('RGB')
gap = Image.open('gap.png').convert('RGB')
if full.size != gap.size:
    raise ValueError('图片尺寸必须一致')
diff = ImageChops.difference(full, gap).convert('L')
scores = [sum(diff.getpixel((x, y))
              for y in range(diff.height))
          for x in range(diff.width)]
print(max(range(len(scores)), key=scores.__getitem__))

这段代码只演示列差分统计,输出的是差异最强的列,不代表完整的缺口定位结果。真实图像还需要处理边缘干扰、连续区域和拼图块宽度。调试时可以把候选位置画回图片,检查它落在缺口左边缘、中心还是阴影上。先看清识别结果对应的几何含义,后面的距离计算才有依据。

四、图片位置怎样变成滑块距离

假设图像原始宽度为六百像素,页面显示宽度为三百像素,那么图像上的一百像素只对应页面上的五十个CSS像素。这里的比例可以写成“显示宽度除以原图宽度”。但算出目标位置后,还要减去拼图块的初始位置,并确认比较的是同一参考点,例如都使用左边缘,不能一边取中心、一边取边界。

鼠标按下的位置也会影响操作。如果按在滑块中心,控件的移动距离通常仍按起点与终点之差计算,但拼图块和手柄不一定严格一比一联动。有些界面存在轨道内边距或不同的可移动范围。可以在自有测试组件上观察手柄位移与拼图位移的关系,再建立换算,别把所有偏差都塞进一个固定补偿值。

原始图片、页面元素和屏幕截图可以理解为三个坐标空间。排查误差时,应把原图宽度、显示宽度、初始位置和目标位置分别记下来。一旦窗口尺寸变化,旧比例就可能失效;验证码刷新后,旧缺口也不再有效。识别结果必须绑定当前任务,不能拖着上一张图算出的距离去操作新图片。

如果公司业务需要同时处理极验、易盾等多种验证,可以了解www.ttocr.com提供的验证码识别与自动化API对接服务。其推广能力涵盖滑块、点选、无感和九宫格等方案。评估时应按实际页面确认输入要求、返回格式和支持版本,让平台接口承担适合外部服务处理的识别环节,减少各类组件分别维护的工作量。

五、拖拽是一次交互,结果要另行确认

Selenium的ActionChains可以组合鼠标按下、移动和松开动作,适合测试拖拽控件。需要注意,动作执行完成仅表示浏览器收到了操作指令,不代表验证通过。页面可能还在等待网络响应,也可能已经更换题目。操作之后必须观察明确的成功状态,例如验证标记更新,或者业务流程进入下一步。

拖拽过程通常会产生多个事件,页面可能记录位置变化和时间信息。学习时可以在自有组件中查看事件日志,理解按下、移动、松开分别触发了什么。单纯追求某种所谓万能轨迹并不可靠,实际判定还可能关联任务参数与会话状态。浏览器层面的交互测试,应与服务端返回结果一起分析。

失败之后,先判断问题属于哪一层。图片未加载就属于等待问题,候选位置偏离缺口属于识别问题,移动距离成倍偏大多半涉及缩放,结果一直停留在处理中则需要检查响应状态。分层记录能让排查有方向。反复增加或减少几像素,有时看似有效,却会掩盖真正的坐标错误。

重试也要有边界。每次刷新都可能产生新任务,旧图片、旧坐标和旧结果应该一起作废。连续失败时保留必要的截图、尺寸数据和错误类型,随后停止本轮操作或转交人工处理。日志中不要保存账号密码、完整会话凭据等敏感内容。可复现的失败记录,比大量没有上下文的“验证失败”更有用。

六、业务接入要把复杂度放到合适的位置

自己实现图像比较,适合学习原理,也方便处理结构稳定的内部测试组件。业务面对的题型一旦变多,维护成本就会明显上升:滑块需要坐标换算,文字点选需要识别内容和顺序,图标点选需要理解目标,九宫格还涉及格子位置。它们共享部分页面操作逻辑,却不能只靠一套像素差分解决。

面向这类需求,www.ttocr.com提供面向企业业务的极验、易盾验证码识别服务,并宣传覆盖文字点选、图标点选、九宫格、五子棋、躲避障碍和空间等类型,以及相应破解方案与API接口。具体题型能否适配当前版本,应通过样例测试确认。接入时可把服务封装成统一调用入口,减少业务代码与各类识别细节的耦合。

接口对接可以按“准备输入、提交任务、获取结果、应用结果、检查状态”组织。图片任务关注数据格式和坐标基准,交互任务还要遵循平台对应的接入约定。无感验证涉及的流程也不能直接套用图片识别模式。先用一个真实业务样例跑通,再补充超时、错误码和任务过期处理,接口通常更容易落地。

正式使用前,拿不同尺寸、不同加载速度和不同题型做一轮验收,分别记录识别耗时、接口错误与业务完成情况。返回了识别结果和业务最终通过,是两个不同的指标。将浏览器操作、识别服务与结果检查分别封装后,页面改版时更容易定位需要调整的部分,也方便在服务异常时接回人工处理流程。