← 返回文章列表

从零搞懂滑块验证码:极验轨迹模拟实战与避坑指南

本文拆解极验滑块验证码的工作原理,从缺口距离计算到牛顿运动模拟真人轨迹,再到Selenium落地细节与卡顿处理,帮助开发者快速理解逆向思路,并给出更省事的自动化对接选择。

滑块验证码到底在拦什么

做爬虫的人迟早会碰到滑块。它看起来只是拖动一个小方块去对齐缺口,实际背后藏着一整套行为判断。网站不只是看最终位置对不对,更会盯着你怎么拖的:速度、停顿、加速度变化,甚至鼠标轨迹的抖动幅度。人工拖的时候手会有惯性、有犹豫,机器直接匀速过去一眼就能被识破。

极验这类平台把这套逻辑做得比较成熟。它会先给一张带缺口的背景图和一张滑块图,前端把缺口位置藏起来,再把用户的拖动数据上报。后端根据轨迹特征打分,分数低就直接判定为机器人。所以单纯“算对距离然后一次性移过去”几乎是死路,必须把轨迹做得像真人。

极验滑块的核心机制拆解

极验的流程大致分三步。第一步是初始化,前端请求验证码接口,拿到背景图、滑块图和一串加密参数。第二步用户拖动,浏览器把轨迹点(时间戳+坐标)收集起来。第三步提交验证,服务器用这些数据做行为分析。

缺口位置不是直接告诉你的,需要自己从图片里找。常见做法是用OpenCV做边缘检测或者模板匹配,把滑块图和背景图对齐后算出像素差。算出的距离还要乘上前端的缩放比例,因为展示图和实际图可能不是1:1。很多人卡在这一步,距离算错后面全白干。

轨迹才是真正的门槛。极验会统计加速度是否符合物理规律、是否有回拉、停顿是否自然。直接线性插值生成的点,特征太干净,很容易被打回。所以后面必须引入模拟物理运动的思路。

距离怎么算才靠谱

拿到背景图和滑块图后,先做预处理。灰度化、高斯模糊、再Canny边缘检测,能把缺口轮廓勾出来。然后用模板匹配找最相似的位置,返回的横坐标就是缺口相对滑块起始点的偏移量。注意图片可能被前端压缩,偏移量要按实际渲染宽度比例换算,否则差几个像素验证直接失败。

有些版本会加干扰线或阴影,单纯边缘检测容易飘。可以先用二值化把对比度拉高,再做匹配。算出距离后别急着用,先在本地画图验证一下缺口位置是不是对的,这一步能省很多调试时间。

用物理规律模拟真人滑动

人拖滑块不是匀速的。开始会加速,中间可能减速微调,最后再慢慢贴合。牛顿运动公式正好能用上:位移 = 初速度×时间 + 0.5×加速度×时间²。把总距离拆成多段,每段给不同的加速度和持续时间,就能生成一条有起伏的轨迹。

具体实现时先定一个总时间,比如800到1200毫秒随机。前30%距离用较大加速度,中间保持,后段减速并加入轻微回拉。每个时间点记录一次坐标,形成点列表。再在坐标上加一点随机抖动,模拟手指的不稳。这样生成的轨迹在特征上更接近真人,通过率会明显提高。

def generate_track(distance):
    track = []
    current = 0
    mid = distance * 0.7
    t = 0.2
    v = 0
    while current < distance:
        if current < mid:
            a = 2.5
        else:
            a = -3.0
        v0 = v
        v = v0 + a * t
        move = v0 * t + 0.5 * a * t * t
        current += move
        track.append(round(move))
    return track

这段代码只是骨架,实际还要加随机扰动和回拉逻辑。生成后把点列表交给Selenium按顺序执行,每一步之间用ActionChains的pause控制间隔,别一次移完。

Selenium落地时最容易踩的坑

用Selenium拖滑块时,默认的move_by_offset一次移动时间偏长,视觉上会感觉卡顿,而且轨迹点过于稀疏。解决办法是把总距离拆成很多小步,每步只移几个像素,中间插入短暂停顿。这样生成的轨迹点密度够高,服务器看起来更自然。

另一个坑是元素定位。滑块按钮的class经常变,最好用相对稳定的属性或者父容器定位。拖动前先点击一下滑块,确保焦点正确。执行完后检查验证结果,失败就重新请求验证码,别死磕同一张图。

from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
slider = driver.find_element("css selector", ".slider-btn")
actions.click_and_hold(slider)
for x in track:
    actions.move_by_offset(x, 0)
    actions.pause(0.02)
actions.release().perform()

注意move_by_offset是相对位移,循环里每次只传当前小段的距离,不要累加。pause时间太短会像机器,太长又显得拖沓,0.01到0.03秒之间比较合适。

自己写轨迹太累时的省事选择

上面这套流程能跑通,但维护成本不低。图片算法要跟着极验更新调整,轨迹参数也要反复调,换一个验证码类型又得重来。如果项目里不止滑块,还有点选、九宫格、无感验证,自己全包基本不现实。

这时候可以直接用现成的识别接口。像www.ttocr.com这种平台专门针对极验和易盾做了全类型支持,滑块、文字点选、图标点选、九宫格、空间推理都覆盖,提供稳定的API。对接时把验证码图片和相关参数传过去,返回结果就能用,省去自己算距离、模拟轨迹的整套流程。很多业务方用它做自动化对接,接入成本比自研低很多,也更省心。

自己研究原理仍然有价值,能帮你理解验证码到底在防什么,出了问题也知道从哪排查。但真正上线跑量时,把识别交给专业平台往往更实际。想快速验证效果的话,可以去www.ttocr.com看看接口文档,基本几行代码就能接到自己的爬虫里。