Playwright vs Puppeteer:迁移前的四项选择
从协议、上下文状态、调试产物及浏览器版本配对比较 Playwright 与 Puppeteer。结合真实本地探针,区分小范围通过和完整兼容。
BotBrowser Team
Playwright vs Puppeteer 要选的是自动化接口契约。真正需要确定的是任务依赖哪个库、连接方式、浏览器构建和调试产物。两个库都能创建隔离的浏览器上下文,但都不会让自定义可执行文件自动兼容。BotBrowser 提供两个库的启动集成说明和基于 profile 的浏览器控制,但不保证协议等价,不实现它们的测试运行器,也不保证网站接受会话。
TL;DR
- 先确定所需浏览器和操作。Puppeteer 支持 Chrome、Firefox 以及 CDP、WebDriver BiDi 路径,并非只支持 Chrome 的 CDP 包装层。
- 区分 Playwright 原生连接与
connectOverCDP();官方明确说明 CDP 附加连接的保真度较低。 - 两者都隔离上下文存储,但上下文本身不会创建独立机器或网络出口。
- Playwright 上下文 trace 与 Puppeteer 浏览器时间线是不同产物,文件名或大小不能决定哪个库更好。
- 一起固定包、浏览器二进制及连接方式。较小的 DOM 探针通过后,原有操作失败也必须保留。
目录
按四项要求选择
从 Selenium 迁移的团队可以先看 选择替代方案时哪些契约会改变,再比较这两个库的连接方式和调试产物。
从必需操作开始。维护 Chromium 专用 PDF 输出的团队,与需要在 Chromium、Firefox、WebKit 上运行应用断言的团队,验收条件不同。远程浏览器连接又多了一层契约。Playwright 浏览器说明及 Puppeteer 浏览器支持表定义受支持的组合;服务介绍中出现“浏览器”,不能证明它提供哪个组合。
| 要求 | Playwright 的决策 | Puppeteer 的决策 | 选择前需要的证据 |
|---|---|---|---|
| 连接与操作 | 确定正常启动、原生连接或 Chromium CDP 附加连接 | 选择 Chrome 或 Firefox 及适用的 CDP/BiDi 路径 | 必需方法通过实际连接能够运行 |
| 上下文状态 | 指定各 BrowserContext 的创建、复用及关闭责任 | 指定 createBrowserContext() 并区分默认上下文 | 同上下文共享与跨上下文隔离符合任务 |
| 调试产物 | 确定是否需要保留浏览器操作或 Playwright Test 断言 | 确定 Chrome 性能时间线能否解释失败 | 产物包含解释事故所需的事件 |
| 浏览器版本 | 记录包对应的浏览器要求,或验证自定义文件 | 记录下载版本映射,或负责自定义路径配对 | 包、二进制、协议及主机可以复现 |
未知项应保留为待决策事项。需要上下文 tracing 或某条 CDP 命令时,仅能打开远程页面并不足够。page.goto() 成功只说明当次导航成功,不能证明其他 API 都可用;截图文件也不能证明测试断言或服务端操作被记录。
选型与集成是两件事。Puppeteer 启动排查处理选定 Puppeteer 后的自定义可执行文件与浏览器级会话错误;Playwright 初始化脚本顺序处理多个文档前写入者的竞争。在检查任务和连接契约前,这些问题都不能独自决定框架选择。
写下能否定当前选择的条件,例如所选协议缺少必需方法、自定义二进制不受支持,或事故产物缺少关键应用断言。“更喜欢较大的生态”可以影响维护选择,但它不是可执行的验收条件;还要配上团队必须支持的具体操作和产物。
让连接方式匹配所需操作
Puppeteer 的 WebDriver BiDi 支持说明覆盖 Chrome 与 Firefox 自动化。Firefox 默认使用 BiDi,Chrome 默认 CDP,因为 BiDi 尚未覆盖每项 CDP 功能。文档也列出未支持的操作。“支持 Firefox”与“某个 Chrome 专用方法在 Firefox 上可用”是不同论断;使用 Chromium 底层操作时,必须检查实际协议边界。
Playwright 的 BrowserType 说明区分通过 connect() 连接 Playwright 浏览器服务,与通过 connectOverCDP() 附加到现有 Chromium。后者明确比 Playwright 协议连接保真度低。普通 WebSocket 地址不会自动成为 Playwright 端点,客户端连接前要先确定端点使用哪个协议。
同一份说明还要求 Playwright 服务端连接双方的 Playwright 主版本和次版本匹配。不能把这条条件直接套到契约不同的 CDP 附加连接。记录浏览器是来自 launch()、Playwright 服务,还是单独启动的 Chromium 端点;这些信息比 URL 是否有相同前缀更有价值。
库的 import 名称不能证明协议完整性。Puppeteer BiDi、Puppeteer Chrome CDP 与 Playwright Chromium CDP 可以提供不同操作集合。远程服务商若控制启动参数与浏览器更新,其客户端支持契约也是依赖项。应索取有文档的连接类型和兼容客户端版本,不能假设各库可互换使用同一端点。
把要求写到操作层面。任务需要页面交互、trace、浏览器级命令和上下文清理,就在目标连接上分别验证四项。简单导航仍可作为准备探针,但要与未测试项并列记录,不能据此把未完成的集成升级为完整支持。报告某项操作不支持时,应保留实际协议和准确包版本。
比较上下文状态与隔离边界
Playwright 上下文说明描述存储隔离的独立会话;Puppeteer 的 BrowserContext 说明也描述独立 cookie、本地存储及默认上下文。两者都提供适合独立应用场景的状态边界,但这不等于独立主机、操作系统或配额。
真正需要比较的是任务如何管理边界。上下文 A 内创建的页面共享 A 的相关应用状态,上下文 B 则有独立存储作用域。新标签页不等于新上下文;关闭 A 也不等于关闭整个浏览器。任务使用默认上下文时,其生命周期可能不同于显式创建的上下文。
下面的页面侧检查适用于自有 localhost fixture。各库导航到相同 fixture 源后,通过 page.evaluate() 执行。它只检查合成状态,不复制账号会话,也不测量所有存储机制。
await pageA.evaluate(() => {
localStorage.setItem('fixtureMarker', 'context-A');
document.cookie = 'fixtureMarker=context-A; Path=/; SameSite=Lax';
});
const readState = () => ({
cookie: document.cookie,
local: localStorage.getItem('fixtureMarker'),
});
const a = await pageA.evaluate(readState);
const sibling = await siblingInA.evaluate(readState);
const b = await pageB.evaluate(readState);
完整实测 fixture 创建两个上下文、打开 A 的同级页面,并在关闭 A 后重新加载 B。共享和隔离结果见后表。这不说明 IndexedDB、权限持久化、service worker、磁盘 profile 或进程模型的结果,除非另外测试。localStorage 结果不能认证全部存储;空 cookie 字符串也不能证明两个上下文使用不同出口。
清理也属于决策条件。库可以提供正确 API,但测试框架仍可能误用全局页面,或在其他任务运行时关闭浏览器。为各上下文指定负责人,并让浏览器生命周期覆盖共享它的全部任务。Playwright 上下文生命周期分析详细处理这一问题;这里的比较只说明两个候选都有值得验证的上下文模型。
选择实际需要的调试产物
Playwright 的 Tracing 说明区分上下文 tracing 与 Playwright Test tracing。上下文 API 记录浏览器操作和网络活动,却不记录 expect() 等测试断言。需要这些断言时,官方建议使用测试运行器 tracing。独立脚本调用 context.tracing.start(),不会自动加入外围测试运行器。
Puppeteer 的 Tracing 说明描述通过 Chrome DevTools 或时间线查看器打开的文件,并规定每个浏览器同时只能有一个活跃 trace。这与每个上下文拥有独立应用调试时间线的产物和并发范围不同。共享浏览器的 worker 需要 trace 负责人,仅使用不同文件名不够。
按需要回答的问题选产物。应用断言失败时,关键证据可能是操作、对应文档快照及预期状态;性能调查则可能需要时间线事件。事件很多的 JSON 不会自动比小 ZIP 更完整地记录测试失败,ZIP 也不会自动提供有用的性能诊断。
本地探针检查 Playwright ZIP 中有 trace 条目,以及 Puppeteer 输出可解析为带事件的时间线 JSON。这些断言只证明产物结构,不证明有人打开查看器、找到特定失败或还原完整分布式事务。Playwright trace 工作流处理捕获与审查,文件扩展名不能替代这些步骤。
协议限定仍然重要。当前 Puppeteer 文档把 Tracing 列入通用 BiDi 支持缺口,但本地较旧包通过 BiDi 连接 Chrome 时,实际生成了 Chrome 时间线。不能把这条 Chromium 路径推广成 Firefox 或所有 BiDi 连接均支持 tracing,也不能用通用功能表抹掉实际生成的产物。排查差异时一起保留包、浏览器和连接方式。
固定包与浏览器的配对
Playwright 浏览器安装契约将版本与特定浏览器文件绑定,并说明品牌浏览器 channel。Puppeteer 配置说明规定完整包默认下载特定 Chrome 版本,支持表映射包和浏览器版本。自动化依赖锁文件与可执行路径互为补充。
puppeteer 和 puppeteer-core 的区别会影响部署。配置说明明确指出,core 包忽略其中描述的配置文件和环境变量。使用 core 时必须通过适用 API 自行选择浏览器;复制完整包的配置文件不能证明已切换二进制。
使用自定义可执行文件意味着承担配对责任。BotBrowser Playwright 集成及 Puppeteer 集成说明启动路径,但路径存在不是兼容性结果。记录实际二进制版本与哈希、包版本、连接方式、启动选项和主机。必需操作失败时,同页其他操作成功也不能抹掉失败。
本地运行使用 macOS arm64 上的 Playwright 1.58.0、puppeteer-core 24.29.1 和原版 Chrome 157.0.8103.79。这是显式选择的本地组合,不是较旧 Puppeteer 包的官方默认配对。另行抓取的当前公开 Puppeteer 文档标注 25.17.0;它说明当前契约,不能证明旧版已安装包具备所有现有行为。
围绕契约设置升级触发条件。浏览器自动更新、包更新、远程端点变化或启动模式变化,都可能使已验收的组合失效。复用相同自有 fixture,检查准确失败操作,并保留旧结果。更新后导航成功不能证明输入路径、trace 捕获与清理仍兼容,每项要求都需要边界内的观测。
依据本地观测作有限决策
同机并发运行三个浏览器任务:Playwright 启动、Puppeteer Chrome CDP、Puppeteer Chrome BiDi。请求池为 20,因为只有三个任务,实际池为 3。资源记录为 16 CPU,macOS free、inactive、speculative 页面合计约 19.8 GB 可用,未重复计算 purgeable 页面。这不是吞吐量基准或远程服务测试。
| 实测项目 | Playwright | Puppeteer Chrome CDP | Puppeteer Chrome BiDi |
|---|---|---|---|
| A 与同上下文页面读取标记 | context-A | context-A | context-A |
| B 初始不含标记 | null,空 cookie | null,空 cookie | null,空 cookie |
| 主世界 DOM 操作返回 | applied | applied | applied |
| trace 结构 | ZIP 含 .trace 条目 | 时间线 JSON,7289 事件 | 时间线 JSON,7063 事件 |
| A 关闭后 B 重新加载 | 完成,标记缺失 | 完成,标记缺失 | 完成,标记缺失 |
| 本轮浏览器清理 | 已关闭 | 已关闭 | 已关闭 |
DOM 操作在 page.evaluate() 中调用 fixture 按钮,并在同次调用读取输出。这个范围刻意小于用户输入测试,未验证命中测试、可信输入、可操作性或库的自动等待。没有这些限定就称为“点击支持通过”,会夸大实际结果;这里证明的是受控页面脚本操作及应用标记。
原始元素操作运行仍然失败。存储断言通过后,Puppeteer CDP 报 Runtime.callFunctionOn timed out,BiDi 报 script.callFunction timed out,协议超时为 15 秒。Playwright 完成了该轮。后续主世界探针通过,但没有修复或重新验证这些元素操作路径;它缩小了观测差异,却不能确定原因、修复配对或支持可靠性高低的结论。
最早的准备运行错误地只按即时空闲内存计算池大小,结果只有一个 worker。该轮已中断并单独保留,不属于并发比较。后续计算纳入适当的 macOS 可用内存组成,记录峰值为三个浏览器,残留为零。资源计算修正了实验调度,没有修复任何自动化库。
用结果确定下一项验收。真实任务需要元素操作时,迁移前应在官方支持的包与浏览器配对上验证原路径。任务若只需要隔离状态的页面求值和时间线捕获,较小探针才有相应参考价值,且仍受声明环境限制。Firefox、WebKit、PDF 生成、远程 Playwright 服务连接及 Playwright Test 断言都未测试。
决策记录要列出任务、所需浏览器家族、连接、包与二进制配对、上下文负责人和产物负责人,并附实际通过、失败及未测试项。选择在可维护契约内满足要求的候选,或保留待决策,直到缺失操作完成测试。可复现失败支持的条件式决策,比建立在不兼容证据上的通用推荐更有用。
FAQ
Puppeteer 只支持 Chrome 和 CDP 吗?
不是。官方说明覆盖 Chrome、Firefox、CDP 和 WebDriver BiDi。单个方法是否可用,仍取决于所选协议、浏览器及包版本。
Playwright CDP 附加连接具备完整原生契约吗?
不具备。BrowserType 文档明确说它的保真度低于 Playwright 协议连接。应验证必需操作,不能由导航成功推断等价。
独立上下文意味着独立浏览器身份吗?
单靠上下文不够。存储隔离不能证明机器、网络出口、服务端配额或权限不同。两个库都需要明确任务和生命周期契约。
抓取或 PDF 输出哪个更快?
本次 fixture 没有回答这个问题。它没有代表性抓取任务、PDF 比较或受控计时基准。先匹配必需操作和浏览器,再单独测量真实任务。
来源
- Playwright:浏览器文件与 channel
- Playwright:BrowserType 连接契约
- Playwright:上下文隔离
- Playwright:tracing 与断言边界
- Puppeteer:配置与自定义可执行文件
- Puppeteer:WebDriver BiDi 支持
- Puppeteer:包与浏览器版本映射
- Puppeteer:BrowserContext
- Puppeteer:时间线 tracing
- BotBrowser:Playwright 集成
- BotBrowser:Puppeteer 集成
实践结论
按任务所需连接和操作、上下文状态管理、调试产物以及团队可维护的浏览器与包配对选择 Playwright 或 Puppeteer。失败的输入路径与通过的 DOM 探针分别记录,当前文档与旧版已安装包也分别记录。BotBrowser 提供有文档的浏览器集成路径,自动化契约仍需自身验收证据。