Rust 重写 Playwright 内存降低 70%
速览
Rustwright 是用 Rust 语言对 Playwright 的完全重写,内存使用量降低了 70%。这一大幅优化意味着在相同硬件上可运行更多浏览器自动化测试实例,显著降低基础设施成本。该成果展示了 Rust 在性能与资源效率上的优势,尤其适合内存密集型任务。
AI 深度解读
背景
Playwright 是微软维护的流行浏览器自动化库,支持 Chromium、Firefox 和 WebKit,通过 Node.js 驱动实现对浏览器的精细控制。然而,其架构依赖一个独立的 Node.js 子进程作为 CDP(Chrome DevTools Protocol)桥接层,导致内存占用较高(Python 绑定下约 133.5 MiB 的客户端库内存),且在自动化指纹检测上存在可识别特征。Skyvern 团队(一家提供云端浏览器会话服务的公司)在 Hacker News 上发布了 Rustwright——一个用 Rust 重写的 Playwright 兼容方案,旨在消除 Node 驱动进程,同时保持 Playwright API 的易用性。该项目目前处于 Alpha 阶段,仅支持 Chromium。
核心内容
Rustwright 是一个用 Rust 编写的浏览器自动化库,为 Python 和 Node.js 提供与 Playwright 相同的 API,但底层不再依赖 Node 子进程,而是直接通过原生 Rust CDP 引擎与 Chromium 通信。其架构对比非常清晰:
- Playwright 架构:用户代码 → 管道(pipe)→ Node 驱动子进程 → CDP → Chromium
- Rustwright 架构:用户代码 → 原始 CDP(raw CDP)→ Chromium
这种设计带来三个核心改进:速度提升约 2.55 倍(本地诊断数据),内存占用降低约 70%(客户端库部分从 133.5 MiB 降至 40.6 MiB),并且移除了 Playwright 驱动附带的所有自动化指纹(如 __playwright__binding__ 全局变量、Runtime.enable 默认启用等)。Rustwright 默认使用真实的 CDP 输入事件(如 Input.dispatchMouseEvent)而非 DOM 模拟调用,并原生支持跨域 iframe(OOPIF)自动附加。
安装与使用
Rustwright 与 Playwright 高度互操作,只需更改一行导入即可:
Python 示例:
pip install rustwright
python -m rustwright install chromium
# 原来:from playwright.sync_api import sync_playwright
from rustwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com")
print(page.title())
browser.close()
Node.js 示例(实验性):
npm install rustwright
// 原来:import { chromium } from 'playwright';
import { chromium } from 'rustwright';
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();
自动化指纹与检测
Rustwright 没有加载 Playwright 的 Node 驱动,因此不会产生以下特征:
- 无
__playwright__binding__等全局变量;后端报告playwright_driver: "none"。 - 默认路径下不启用
Runtime.enable,关闭了isAutomatedWithCDP控制台序列化泄露。 - 默认规范化 headless 身份:禁用
--disable-blink-features=AutomationControlled,重写 User-Agent 中的HeadlessChrome/为Chrome/,安装navigator.webdriver清理脚本。
重要声明:Rustwright 并非“不可检测”——它仍然使用 CDP 原语(如 Target.setAutoAttach、初始化脚本和延迟启用的 Runtime.enable)。它不能绕过 CAPTCHA 或 Cloudflare,仅保证不出现 Playwright 特有的自动化指纹,同时提供基础的信号清洁。
性能与内存诊断
- 速度:在本地一次运行中(预热浏览器,5 次迭代),Rustwright 在 17 个测试用例的均值上胜出 16 个。
- 内存:客户端库内存占用从 Playwright-python 的 133.5 MiB 降至 Rustwright 的 40.6 MiB(约 70% 减少);另一个异步并发测试显示约 66% 减少。注意:这些是演示级诊断,并非受控 CI 证据,且整体进程内存中 Chromium 占主导,差异不大。
当前状态与限制
- Alpha 阶段:API 形状已覆盖,但未实现完整的行为一致性。
- API 覆盖率:Python 同步 API 约 96%(515/536 方法,其中 411 个由共享一致性注册表测试);异步 API 488/536。
- 仅 Chromium:Firefox 和 WebKit 会直接报错。
- Node.js 绑定早期:仅桥接了
launch、newPage、goto、click、fill、title、textContent、evaluate、screenshot、close;上下文、路由、追踪和定位器目前仅支持 Python。 - 异步并发(Python):异步 API 通过线程包装同步引擎,建议用于 ≤25 个并发工作流/进程,不适合高扇出。
- OOPIF 残留问题:非主框架的
JSHandle后续操作、拖拽/截图/边界框存在缺口。 - 自动化检测部分:本地运行中 4 个公开指纹目标干净了 3 个(CreepJS 仍能检测到 headless),无不可检测性承诺。
路线图 & 最近更新
- 路线图:Kotlin 绑定、新语言绑定扩展(超越 Alpha 子集)、Rustwright MCP 服务器(为 MCP 兼容 AI 代理暴露浏览器自动化工具)、CI/测试箱基准证据、Node.js 表面扩展、关闭 OOPIF 缺口。
- 最近已发布:Go、Java、C#/.NET、Ruby、PHP 绑定(通过共享 C ABI 实现),以及原生 Rust API;Python 包已发布到 PyPI;Node.js 包已发布到 npm;原生异步引擎(基于 Tokio CDP 核心);OOPIF 自动附加与扁平化 CDP 会话;515/515 共享一致性测试套件通过;默认路径关闭了
Runtime.enable控制台序列化泄露。
远程浏览器会话(Skyvern)
Rustwright 驱动浏览器,但运行浏览器需要环境。Skyvern 团队提供托管的浏览器会话作为付费服务,用于资助该项目。功能包括:持久化云端浏览器(登录、Cookie、标签状态跨会话保留)、可配置超时(5 分钟到 24 小时)、21 个国家代理、实时查看与交互。用户通过 browser_address CDP 端点连接,Rustwright 支持 connect_over_cdp(目前仅 Python,Node.js 尚不支持)。
