滑动验证通过采集鼠标时间戳、坐标序列、加速度突变及浏览器指纹识别机器人;匀速直线轨迹必被拦截,须用贝塞尔曲线生成带噪声、随机延迟的拟人化轨迹,并配合JS事件注入与环境指纹伪装。

滑动验证的轨迹检测原理决定了纯数学函数无效
几乎所有主流滑动验证(如极验、腾讯云验证码)都会采集鼠标移动过程中的时间戳、坐标序列、加速度突变点,甚至结合浏览器指纹判断是否为真实 human 操作。直接用 pyautogui.moveTo() 或 selenium.ActionChains.drag_and_drop_by_offset() 生成匀速直线轨迹,几乎必然被识别为机器人——因为真实拖拽存在微小抖动、停顿、非线性加速度变化。
必须模拟带噪声和节奏感的贝塞尔曲线轨迹
真实拖拽不是“从 A 到 B 的直线”,而是手部肌肉控制下的近似三次贝塞尔运动:起始有小幅试探性移动,中途可能因视觉反馈微调方向,末尾常有减速停顿。推荐用 bezier 库生成控制点,再叠加高斯噪声和随机延迟:
import bezier import numpy as np import time <h1>定义起点、两个控制点、终点(x 坐标为主,y 可固定或微扰)</h1><p>nodes = np.asfortranarray([ [0.0, 10.0, 80.0, 100.0], # x [0.0, -2.0, 3.0, 0.0] # y(轻微上下浮动) ]) curve = bezier.Curve(nodes, degree=3)</p><h1>采样 30~50 个点,加入 ±1.5px 随机偏移和 20~80ms 不等间隔</h1><p>s_vals = np.linspace(0, 1, np.random.randint(30, 51)) points = curve.evaluate_multi(s_vals) for i, (x, y) in enumerate(points.T): noise_x = np.random.normal(0, 1.5) noise_y = np.random.normal(0, 0.8) final_x, final_y = int(x + noise_x), int(y + noise_y)</p><h1>使用 pyautogui 移动到该点(注意:需提前切换到目标窗口)</h1><pre class="brush:python;toolbar:false;">pyautogui.moveTo(final_x, final_y) time.sleep(np.random.uniform(0.02, 0.08))
- 控制点不能对称排布,否则轨迹太“工整”;建议第二控制点 x 偏移略小于总距离的 70%,y 偏移带负值模拟抬手试探
-
pyautogui默认走绝对坐标,务必先用pyautogui.getWindowsWithTitle()定位并激活目标浏览器窗口,否则移动发生在桌面空白处 - 采样点数少于 25 或大于 60 都易被风控:太少失真,太多像程序生成
绕过前端 JS 行为采集才是关键,不是只改鼠标路径
滑动控件通常会监听 mousemove、mousedown、mouseup 并记录事件时间戳与 clientX/clientY。即使你用物理鼠标操作,若页面 JS 检测到 event.buttons === 0 或 event.movementX 异常,仍会拒绝提交。因此必须配合 Selenium 注入真实事件:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
driver.execute_script("""
const el = arguments[0];
const rect = el.getBoundingClientRect();
const startX = rect.left + 20;
const endX = rect.right - 20;
<p>// 模拟 mousemove 轨迹(用上面生成的 points 数组)
for (let i = 0; i setTimeout(r, arguments[2][i])); // 对应每个点的 delay
}
""", slider_element, trajectory_points, delays_list)</p>
- 仅靠
pyautogui移动光标无法触发页面内绑定的事件监听器,必须用execute_script主动派发事件 - 所有坐标必须基于元素
getBoundingClientRect()计算,硬编码像素值在不同分辨率下失效 - 不能省略
await和setTimeout,否则所有事件瞬间发出,被识别为脚本行为
环境指纹比轨迹更致命,headless Chrome 必须伪装
即使轨迹完全拟真,若 WebDriver 启动的是无头 Chrome 或未覆盖 navigator.webdriver、plugins、languages 等字段,滑动成功后提交时仍会返回 "invalid session" 或 "behavior not allowed" 错误。
- 禁用
--headless,使用普通 Chrome 实例(options.add_argument("--disable-gpu")可减负) - 注入 JS 覆盖关键属性:
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"}) - 设置真实
user-agent和accept-language,且二者需匹配(如zh-CN,zh对应Mozilla/5.0 ... Chrome/124.0.0.0 Safari/537.36) - 禁用
--enable-automation和--disable-blink-features=AutomationControlled,否则chrome.runtime暴露自动化痕迹
轨迹只是表层,真正卡住多数人的,是没意识到滑动验证服务端校验的是整个浏览器会话的可信度,而非单次拖拽动作本身。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










