invisible_playwright 如何让点击像真人:贝塞尔曲线、isTrusted 与人类化输入解析
【免费下载链接】invisible_playwrightPlaywright that anti-bots cannot see, so no captchas: same API, anti-detect stealth headless Firefox, undetected fingerprint, bypass bot detection, Python web scraping and browser automation.项目地址: https://gitcode.com/gh_mirrors/in/invisible_playwright
做浏览器自动化的人都知道一个尴尬事实:你的脚本再快、选择器再准,网站依然可能在第一次点击后就弹出验证码。原因在于反爬系统早就从"查指纹"进化到了"看行为"——你的鼠标是不是瞬移的?按键间隔是不是等距的?点击事件是不是脚本伪造的?invisible_playwright正是为此而生的反检测 Python 库:它包装了一个在 C++ 源码层打补丁的 Firefox,让同样的 Playwright API 跑出一个指纹无法被识别、输入像真人的浏览器。其中"输入像真人"由三套机制完成:浏览器原生输入路径带来的isTrusted 可信事件、贝塞尔曲线驱动的自然鼠标轨迹、以及逐会话随机化的人类化节奏。这篇文章带你逐层拆解这套人类化输入系统是怎么工作的。
为什么"像真人"比"不被发现"更难
reCAPTCHA v3、hCaptcha、Cloudflare Turnstile 这类无感验证并不只读你的浏览器指纹,它们会给每一次交互打"风险分"。一个行为完全像真人的会话,可以拿到 0.90 这种"极低风险"的分数,从而根本不触发挑战页。
而"行为像人"这件事,检测器只需要几行 JavaScript 就能开始验证。最便宜的一关只有一个布尔值:isTrusted。
| 检测信号 | 页面 JS 伪造的事件 | invisible_playwright 驱动的事件 |
|---|---|---|
isTrusted | false | true |
| 输入源(pointerType) | 未知或 null | 真实鼠标 |
| 压力值(pressure) | 恒定不变 | 随按键状态变化 |
| 事件时间戳 | 完美等距 | 不规则、符合设备速率 |
第一关:isTrusted——无法伪造的信任位
很多"人类化鼠标库"都在页面向你推销贝塞尔曲线,但它们全部止步于同一个死穴:只要是页面 JavaScript 用dispatchEvent派发出来的事件,isTrusted就永远是false——这个标志由浏览器引擎在构造事件时设置,只读、无 setter,页面脚本永远无法把它改成true。
invisible_playwright 的做法绕开了页面层:它不与页面脚本打交道,而是通过协议向打补丁的 Firefox 发送输入请求,由引擎自身的原生输入机制合成事件——也就是把硬件鼠标报告转成 DOM 事件的同一条内部路径。事件由引擎制造,所以天然携带isTrusted=true,并且被标记为真实鼠标设备、带有随按键状态变化的压力值。
你可以在同一个页面上对比两种来源:驱动式点击报告trusted=true,而dispatchEvent注入的事件报告false。相关机制与对照实验见 docs/playwright-clicks-istrusted.md。
注意一个常见误区:
isTrusted=true只是必要条件,不是充分条件。它让会话通过了"来源检查",但轨迹形状、时间节奏、空闲行为仍然是独立的考题。
第二关:贝塞尔曲线画出瞬移之外的轨迹
裸的page.mouse.move()会让光标从(0, 0)直接"瞬移"到按钮上,中间没有任何事件——这本身就是一眼假的签名。invisible_playwright 默认开启人类化(humanize默认开启),把每一次点击、悬停、拖拽都变成一段沿曲线滑行的过程。
核心生成器在 src/invisible_playwright/_motion.py,它把一次移动拆成一条流水线:
- 控制多边形(贝塞尔骨架):在起点与终点之间放 1~3 个控制点,曲线弧度不是写死的常量,而是由会话种子 + 一个"手臂枢轴角"决定。同一个方向的两点之间,不同会话会弯出左弧或右弧——这就是两个"人"的区别。
- Fitts 定律定时长:移动耗时随距离和目标大小变化(
T = a + b·log₂(D/W+1)),点到 20px 小按钮比划过 200px 大区域更慢,而不是所有动作都花 1 秒。 - 钟形速度剖面:速度在两端为零、在中间某处达到峰值(峰值位置每次移动都随机),模拟人手"慢启动—快滑—减速停靠"的节奏。
- 微震颤(tremor):每个内部路点都叠加二维独立的高斯抖动(沿行程 + 垂直行程两个分量),两端精度最高——和真人瞄准时"到位才稳"一致。
- 偶发过冲与回拉:约 14%~48% 的移动会越过目标再修正回来(概率同样按种子抽取),"100% 精准单调"同样是签名。
- 重复像素保持:低速段允许连续两个事件落在同一设备像素上——"永远不重复"和"永远重复"都是假。
这些参数还有一个巧妙之处:全部来自会话种子,没有任何硬编码常量。写死的曲线族可以被一次测量、永久识别,还会把你控制的所有账号串在一起;而种子派生的参数让每个会话的运动"家族"都不同。同一颗种子则逐字节复现同一条路径,方便复现失败案例。纯数学性质可以直接用 tests/test_motion.py 验证,无需启动浏览器。
第三关:人类化节奏——点击、打字与"没事干"的时间
轨迹只是半个问题,另一半是两次移动之间手在干什么。invisible_playwright 在 src/invisible_playwright/_behaviour.py 里为每个会话抽取一个"指针人格"(PointerPersona),控制:
- 点击节奏(
plan_click):鼠标键按住约 58~124ms(对数正态分布,而非一次网络往返的 2ms);双击间隔 95~215ms——低于几十毫秒的双击没有任何操作系统会承认。 - 打字节奏(
plan_typing):每个字符有独立的按键保持时长与间隙,并且换手的两个字符更快、同键重复更慢——这是真实打字动力学中最稳的结构;还随机插入"思考停顿"。 - 空闲行为(
plan_idle):人在读页面时手不会完全静止,光标会做像素级的微调整(settle)、缓慢漂移(drift)、把光标停到段落之外(park)、或跟着文字行缓慢横扫(trace)。 - 滚动伴随(
plan_scroll):滚轮转动时手掌会带动光标蠕动一两像素。
这些计划的时间线由 src/invisible_playwright/_pacing.py 的Pacer状态机按绝对截止时刻下发:事件间最小间隔锁定在 8ms(真实鼠标 125Hz 的物理下限),宁可丢弃迟到事件也不发送两台机器都不存在的"事件速率",且绝不在同一瞬间发两个事件。
种子可复现:像人,但不玄学
这套系统的公开用法几乎零成本——它是默认行为:
from invisible_playwright import InvisiblePlaywright with InvisiblePlaywright(seed=42) as browser: # humanize 默认开启 page = browser.new_page() page.goto("https://example.com") page.click("#submit") # 光标沿曲线滑向按钮,事件字段如同真实设备seed=42意味着同一次运动可以逐字节重放:不同种子得到不同"手型",同一种子得到完全相同的轨迹与节奏。想恢复瞬移的旧行为,可设humanize=False(见 src/invisible_playwright/init.py)。
如何验证你的点击真的"像真人"
在目标页挂一个监听器即可自查:
document.addEventListener('click', e => console.log(e.isTrusted, e.pointerType, e.pressure, e.timeStamp));isTrusted必须全为true,出现一个false就是决定性证据;pressure悬停时应为 0,按键按下到抬起之间应非零;- 时间戳间隔必须不规则,等距间隔是循环脚本的签名;
- 坐标不应按常量步进推进。
更完整的自查清单见 docs/human-mouse-movement.md,行为生物特征层面的讨论见 docs/mouse-dynamics-behavioural-biometrics.md;点击与打字的节奏测试分别在 tests/test_click_rhythm.py 与 tests/test_typing_rhythm.py。
总结:三道关卡的正确顺序
- 信任位:事件必须由浏览器引擎原生路径产生,
isTrusted才可能为true——这一关不过,曲线再漂亮也白搭; - 轨迹形状:种子派生的贝塞尔曲线 + Fitts 定律 + 震颤 + 过冲,让路径有"手"的家族特征而非库的常量;
- 宏观节奏:点击保持时长、打字手感、空闲漂移与滚动伴随,让整段时间线上有"人"在。
人类化输入解决的是"是否真人在使用"这道题,机器层面的指纹与网络信号是另一道题。但顺序是明确的:先把信任位做对,曲线才值得调。invisible_playwright 把三者做成了默认行为,你只需要照常写 Playwright 代码。
【免费下载链接】invisible_playwrightPlaywright that anti-bots cannot see, so no captchas: same API, anti-detect stealth headless Firefox, undetected fingerprint, bypass bot detection, Python web scraping and browser automation.项目地址: https://gitcode.com/gh_mirrors/in/invisible_playwright
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考