☰
invisible_playwright 架构深潜:wrapper、invisible_core 与 Juggler 如何协同实现反检测浏览器
2026/9/30 5:11:18 网站建设 项目流程

invisible_playwright 架构深潜:wrapper、invisible_core 与 Juggler 如何协同实现反检测浏览器

【免费下载链接】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 是一个用 Playwright 原生 API 驱动反检测 Firefox的 Python 库:同一份代码、同样的page.goto/page.click,底层却是一个在 C++ 源码级打补丁的无头/有头浏览器,配合确定性指纹,让 reCAPTCHA、Cloudflare 等反机器人系统"看不见"自动化痕迹。它的秘密不在某个魔法函数,而在三层架构的精密分工——wrapper 负责门面、invisible_core 负责身份、Juggler 负责驱动。本文带你逐层拆解它们如何协同工作。

一张表看懂三层架构 🧩

层角色关键模块
wrapper(外壳层)用户唯一接触面:InvisiblePlaywright上下文管理器、版本守卫、人性化鼠标launcher.py、_session.py、_cursor.py
invisible_core(身份层)种子 → 指纹 → 浏览器偏好的"唯一事实来源",外加代理、时区、地理信息_fpforge/、seal 封印校验
Juggler(驱动层)进程内 Python 协议服务器,经管道直连 Firefox 内置的 Juggler 端点,彻底告别 Node 驱动_juggler/(connection.py、server.py、dispatcher.py)

一句话概括数据流:你写的 Playwright 调用 → wrapper 翻译并注入人性化动作 → invisible_core 提供的偏好/指纹随启动参数进入浏览器 → Juggler 管道把每条命令送达 Firefox 内部协议端点。

第一层:wrapper —— 两行代码切换的入口

对使用者而言,整个架构只有一个面孔:InvisiblePlaywright。切换只需两行:

- from playwright.sync_api import sync_playwright + from invisible_playwright import InvisiblePlaywright

这层做了三件"看不见的重活":

  • 版本守卫:导入瞬间 _pin.py 就校验已安装的 invisible-core 是否精确匹配声明版本,不匹配会尝试自动修复而不是静默出错;_engine.py 再校验 Playwright 客户端版本落在引擎"封印"(seal)声明的范围内——因为 Juggler 协议是闭集,超范围的客户端会在创建上下文时直接失败。
  • 同步/异步合一:launcher.py(sync)与async_api.py(async)两个类原本有 80% 重复代码,后来抽出了 _session.py 作为共享会话逻辑,保证两条 API 路径行为永远一致。
  • 人性化注入:_cursor.py 不新增任何 API,而是拦截page.click/page.hover等所有指针动作的内部汇聚点,把"瞬移光标"改写成由种子绘制的贝塞尔曲线轨迹——同样的seed可以精确重放同样的运动。

第二层:invisible_core —— 指纹的唯一事实来源 🧬

反检测浏览器被抓包的头号原因,是各指纹面互相矛盾(比如 User-Agent 说 Windows,字体却像 Linux)。invisible_core 的解法是:所有值由一个种子统一采样,在页面能提问之前就锁定。

with InvisiblePlaywright(seed=42) as browser: # 同一 seed = 同一 GPU、Canvas、音频指纹 ...
  • 种子 → Profile → 偏好:generate_profile用贝叶斯采样器从种子派生约 200 个字段(GPU、屏幕、字体、音频、时区……),再由compose_session_prefs翻译成 Firefox 偏好项写入配置。想要固定某些字段,用pin=即可,详见 docs/pinning.md。
  • 引擎封印:ensure_binary下载打过补丁的 Firefox 二进制,seal 文件记录其构建指纹,_engine.py 在启动前后双重校验——连application.ini被手改都能被协议层上报的版本戳识破。
  • 网络一致性:时区从出口 IP 离线解析、DNS 强制走代理、WebRTC 只提供一个承载代理出口的合成 ICE 候选——本地真实 IP 无处泄漏:

指纹站看到的效果:Bot、开发者工具、虚拟机等信号全部"Not detected":

第三层:Juggler —— 没有 Node 的驱动通道 🚀

传统 Playwright 是"Python 客户端 → Node 驱动 → CDP/Juggler"三段式,而 invisible_playwright 在 2026-08-28 删除了整个 6MB 的 Node 驱动:现在回答 Python 客户端的,是进程内的 Python 服务器,位于 _juggler/。

它的管道契约直接读自 Firefox 源码而非猜测:

  • 消息是零字节分隔的 JSON(不是换行);
  • POSIX 上文件描述符硬编码为fd 3 / fd 4;Windows 上用可继承的句柄,经环境变量PW_PIPE_READ传递;
  • 命令行必须带-juggler-pipe,否则 Windows 上管道根本不激活。

协议层有两个硬核设计(见 dispatcher.py 的模块注释):

  1. 顺序即协议:每个新对象必须先发__create__宣告、再返回 channel 句柄,乱序不是"偶尔能跑"的竞态,而是硬失败;
  2. 方法显式路由:每个协议对象用显式的METHODS字典声明可响应的方法名,杜绝getattr动态路由带来的攻击面。

而 server.py 中的每个字段形状都来自scripts/capture_protocol.py对真实会话的协议录制——比如goto/click发给的是 Frame 而非 Page,mouseMove在一次人类化点击中会到达 19 次,因为光标真的在移动。

一次点击如何穿过三层 🔍

以page.click("#submit")为例,完整旅程是:

  1. wrapper 层:_cursor.py拦截这次点击,按种子展开成一条带按压、带节奏的贝塞尔轨迹,拆成多次mouse.move加一次落点;
  2. 驱动层:每条指令经 Juggler 管道(零字节分隔 JSON)送达,dispatcher按 guid 路由给对应协议对象,事件顺序严格符合"先创建、后引用";
  3. 引擎层:Firefox 内部由真实输入路径派发事件,所以event.isTrusted是"真的真",而非 JS 垫片伪造;
  4. 身份层兜底:整个会话中,navigator、Canvas、WebGL、WebRTC 全部回答来自同一个种子画像,页面无论怎么交叉验证都不会自相矛盾。

结果就是检测站视角下的"0% headless、0% stealth 特征":

延伸阅读 📚

  • 完整入口与用法:README.md
  • 指纹字段固定(pinning)详解:docs/pinning.md
  • 指南总目录(含检测原理分组):docs/guides.md
  • 测试如何验证各层行为:tests/(如 test_juggler_connection.py、test_fingerprint_consistency.py)

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询