Selenium+ActionChains被识破主因是鼠标轨迹缺乏人类特征;需用贝塞尔曲线生成非线性路径,叠加随机抖动、加速度和停顿,并配合CDP篡改navigator属性、禁用自动化标识等综合反检测策略。

为什么 selenium + ActionChains 模拟鼠标移动总被识破
因为多数网站检测的不是“有没有移动”,而是“移动轨迹是否像人”——匀速直线、固定起始点、毫秒级时间戳一致、无加速度变化,这些全是机器人特征。
真实鼠标移动有加速度、微小抖动、非线性路径、不规则停顿。直接用 ActionChains.move_by_offset() 或 move_to_element() 生成的轨迹,在 document.addEventListener('mousemove', ...) 和 canvas 轨迹采样中一眼就被标记为 bot。
- 避免用
perform()一次性执行整段位移;拆成 10–30ms 间隔的微小偏移 - 不要从 (0, 0) 开始;先用
move_to_element_with_offset(el, x, y)偏移一个随机像素再开始轨迹 - 加入 2–5px 的随机横向/纵向抖动(每次偏移后加
move_by_offset(randint(-2,2), randint(-2,2))) - 关键:用贝塞尔曲线生成坐标序列,而不是线性插值——人眼无法察觉,但风控系统会校验轨迹曲率
如何用 bezier 曲线生成自然鼠标轨迹(Python + selenium)
核心是把起点→终点映射为三次贝塞尔曲线上的离散点,再逐点驱动 ActionChains。不用第三方绘图库,只靠基础数学计算。
示例中 get_curve_points() 返回的是相对偏移列表,每步控制在 3–8px 内,总步数控制在 30–60 步之间,太短像瞬移,太长易超时:
def get_curve_points(start_x, start_y, end_x, end_y):
cp1_x = start_x + (end_x - start_x) * 0.3 + randint(-15, 15)
cp2_x = start_x + (end_x - start_x) * 0.7 + randint(-15, 15)
cp1_y = start_y + (end_y - start_y) * 0.4 + randint(-10, 10)
cp2_y = start_y + (end_y - start_y) * 0.6 + randint(-10, 10)
points = []
for t in [i/50 for i in range(51)]:
x = (1-t)**3*start_x + 3*(1-t)**2*t*cp1_x + 3*(1-t)*t**2*cp2_x + t**3*end_x
y = (1-t)**3*start_y + 3*(1-t)**2*t*cp1_y + 3*(1-t)*t**2*cp2_y + t**3*end_y
if points:
points.append((int(x - points[-1][0]), int(y - points[-1][1])))
else:
points.append((int(x - start_x), int(y - start_y)))
return points
调用时注意:move_to_element() 后必须 pause(0.1) 再开始轨迹,否则起点坐标不准;每步 move_by_offset(dx, dy) 后加 pause(uniform(0.01, 0.03))。
哪些行为组合会让风控直接拦截(不止鼠标)
单模拟鼠标没用。现代反爬会关联分析:鼠标轨迹 + 页面停留时长 + 滚动节奏 + 键盘事件缺失 + navigator.webdriver === true 状态。
- 页面加载后立刻操作?错。等
document.readyState === 'complete'且performance.timing.domContentLoadedEventEnd > 0再开始 - 全程没滚动?补上 1–2 次缓慢滚动(用
execute_script("window.scrollBy(0, 200)")+ pause,别用scroll_to()) - 没触发过键盘事件?哪怕只是
send_keys(Keys.NULL)或随机按一次Tab,也能降低风险分 -
webdriver属性仍为 true?启动时必须加options.add_experimental_option("excludeSwitches", ["enable-automation"])和options.add_argument('--disable-blink-features=AutomationControlled'),再执行driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {...})覆盖navigator属性
Chrome DevTools Protocol(CDP)能绕过哪些前端检测
CDP 是目前最有效的底层干预方式,比 JS 注入更早、更彻底。它能在页面任何脚本执行前就修改运行时环境,比如伪造 chrome.runtime、屏蔽 cdc_ 变量、重写 eval.toString。
常见生效点:
- 覆盖
navigator.permissions.query返回{state: "granted"},否则部分风控会因“无权限访问传感器”判为 headless - 删除
window.chrome下所有含cdc_前缀的属性(selenium 旧版驱动残留) - 重写
HTMLMediaElement.prototype.canPlayType返回真实值,否则视频类站点可能拒绝渲染 - 禁用
WebGLVendor检测:通过 CDP 设置Emulation.setEmulatedMedia并伪造userAgent,比 JS 注入更稳
CDP 不是万能的——它不能改变浏览器指纹中的 Canvas / AudioContext 特征,那些得靠代理层或专用浏览器内核(如 undetected-chromedriver3 封装的 patch)。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











