首页
/ Puppeteer 是什么:掌控 Chrome 与 Firefox 的 JavaScript 自动化利器

Puppeteer 是什么:掌控 Chrome 与 Firefox 的 JavaScript 自动化利器

2026-09-07 10:14:45作者:田桥桑Industrious

导读:本文以 docs/guides/what-is-puppeteer.md 为骨架,系统解读 Puppeteer 的核心定位、两大浏览器自动化协议(DevTools Protocol 与 WebDriver BiDi)、Headless 运行方式与六大典型能力场景,并结合本仓库的源码、API 文档与示例代码深入印证其底层实现。阅读后你将理解 Puppeteer 的架构全貌、默认协议选择逻辑与适用边界,并能立即写出第一个可运行的浏览器自动化脚本。

Puppeteer 是什么

Puppeteer 是一个 JavaScript 库,它对外提供一套高层级 API,用于通过 DevTools Protocol(简称 CDP)或 WebDriver BiDi 协议控制 Chrome 或 Firefox 浏览器。作为对比,同样是自动化工具,WebDriver Classic 要求必须独立启动浏览器进程再连接,而 Puppeteer 从设计上就与浏览器的启动、页面创建、交互操作流程深度绑定,开箱即用。

在协议选择上,Puppeteer 采取了“自动择优”的策略,而这一策略在仓库源码中写得非常直白。在 BrowserLauncher.ts 中可以看到:

let {protocol} = options;

// Default to 'webDriverBiDi' for Firefox.
if (this.#browser === 'firefox' && protocol === undefined) {
  protocol = 'webDriverBiDi';
}

...

if (this.#browser === 'firefox' && protocol === 'cdp') {
  throw new Error('Connecting to Firefox using CDP is no longer supported');
}

从中可以提炼出两条关键事实:

  • Firefox 默认走 WebDriver BiDi,且显式指定 Firefox + CDP 组合会直接抛出错误(即通过 CDP 连接 Firefox 已不再被支持);
  • Chrome 默认走 CDP,因为 WebDriver BiDi 尚未覆盖全部 CDP 特性,需要时你可以通过 protocol: 'webDriverBiDi' 显式切换。

默认无头,可选有头

Puppeteer 默认以 headless(无界面)模式运行浏览器,这意味着你不需要一个真实的显示器或桌面环境,非常适合跑在 CI、服务器与容器中;同时它也完全支持配置成可见的 “headful”(有头)浏览器运行,便于在开发调试阶段观察页面实际表现。关于这一主题的完整配置方法,可阅读仓库内文档 Headless mode

Puppeteer 能做什么

正如原文档强调的:“大多数你在浏览器里手动能做的事情,都可以用 Puppeteer 自动化完成。” 结合仓库内的配套指南(见 docs/guides 目录),它的能力主要覆盖以下六大方向。

1. 自动化交互与 UI 测试

自动化完成表单提交、UI 测试、键盘输入、鼠标点击、滚动、拖拽等一整套“真人操作”。

2. 构建自动化测试环境

你可以直接用最新的 JavaScript 与浏览器特性来搭建端到端测试环境。Puppeteer 不会因为运行在自动化脚本里就限制你用新的语言特性——它会把 page.evaluate() 中的代码直接在浏览器环境执行。

本仓库自带的测试工程位于 test/src,包含 76 个 TypeScript 测试文件,覆盖了从页面跳转、网络拦截到截图对比等大量行为;同时 test/TestExpectations.jsontest/TestSuites.jsontest/CanaryTestExpectations.json 构成了跨浏览器、跨协议的测试矩阵,可作为构建大型自动化测试基础设施时的参考。

3. 采集 Timeline Trace 做性能诊断

可以对站点抓取 Timeline trace(时间线轨迹),用于定位页面加载与运行时性能瓶颈。这类底层能力在 CDP 协议下通过 Tracing 域实现,对应的 Puppeteer 封装为 Tracing(提供 start/stop 方法)。

4. 测试 Chrome 扩展

Puppeteer 支持自动化测试 Chrome 扩展:可以安装扩展、打开扩展页面、访问其 popup 逻辑。仓库内有专门文档 chrome-extensions.md,还提供了一个可直接运行的完整示例工程 examples/puppeteer-in-extension(内含 manifest.json、扩展页面与配套脚本),相关 API 见 browser.installextensionbrowser.extensions

5. 生成页面截图与 PDF

对页面进行截图(含整页长截图)以及生成 PDF 文件,是 Puppeteer 被使用最广的能力之一:

6. 爬取 SPA 并生成预渲染内容

Puppeteer 可以爬取 SPA(单页应用) 并抓取其真实渲染后的 DOM,从而生成预渲染(pre-rendered)内容——也就是常说的 “SSR”(Server-Side Rendering)的一种实现路径。这让搜索引擎爬虫与低 JS 环境也能拿到完整内容。

7. 更多领域能力(仓库印证)

在上述六大方向之外,本仓库的 docs/guides 还沉淀了围绕 Puppeteer 周边生态的完整指南,例如:

深入理解两大自动化协议

理解 “What is Puppeteer” 的关键,是弄清楚它背后的双协议架构

CDP(DevTools Protocol)

DevTools Protocol 是 Chrome 为开发者工具提供的调试协议,历史最悠久、功能覆盖最全。Puppeteer 以 CDP 为默认协议连接 Chrome,并在其上封装出截图、性能追踪、网络拦截等丰富能力。仓库中对应的协议实现位于 packages/puppeteer-core/src/cdp,你可以直接读到 PageBrowserConnection 等在 CDP 层上的具体实现。

WebDriver BiDi

WebDriver BiDi 是 W3C 正在推进的新一代跨浏览器自动化协议,目标是融合 WebDriver “Classic” 与 CDP 双方优点:支持双向通信(bi-directional communication),从而默认就具备低延迟、快速度的特性,同时提供低层级的精细控制。它让“一套 API 同时驱动 Chrome 与 Firefox”成为现实——Firefox 侧甚至已经关闭了 CDP 通道,全面转向 WebDriver BiDi。

仓库对 WebDriver BiDi 的实现位于 packages/puppeteer-core/src/bidi。关于“哪些 Puppeteer 特性已完整支持 BiDi、哪些暂不支持”的详细能力矩阵,请以仓库内文档 docs/webdriver-bidi.md 为准——其中的关键提示是:当某个特性在 WebDriver BiDi 下尚未支持时,调用会抛出 UnsupportedOperation 错误,而不是静默失败。

例如,通过 BiDi 同时驱动 Firefox 与 Chrome 的最小示例为:

import puppeteer from 'puppeteer';

// Firefox:默认即使用 WebDriver BiDi
const firefoxBrowser = await puppeteer.launch({
  browser: 'firefox',
});
const page = await firefoxBrowser.newPage();
// ...
await firefoxBrowser.close();

// Chrome:显式声明使用 WebDriver BiDi(否则默认走 CDP)
const chromeBrowser = await puppeteer.launch({
  browser: 'chrome',
  protocol: 'webDriverBiDi',
});
// ...
await chromeBrowser.close();

关于支持的浏览器与系统版本约束,可查看 supported-browsers.mdsystem-requirements.md

Headless 模式:默认与三种用法

“Puppeteer 默认 headless 运行” 这句话包含了丰富的细节。官方文档 headless-modes.md 给出了三种明确的启动方式:

// 1. 默认:等价于 {headless: true},即新版 Headless 模式
const browser = await puppeteer.launch();

// 2. 旧版独立产物 chrome-headless-shell(更轻量、纯自动化场景性能更优)
const browser = await puppeteer.launch({headless: 'shell'});

// 3. 有头(headful)模式:可见的浏览器窗口,便于人眼调试
const browser = await puppeteer.launch({headless: false});

从源码结构看,在 v22 之前 Puppeteer 默认使用旧版 Headless 模式;如今旧版被拆分为独立的 chrome-headless-shell 二进制。它不会完全复刻完整版 Chrome 的全部行为,但在不需要完整浏览器特性的纯自动化任务里性能表现更好——如果你的场景对性能更敏感,优先选择 'shell'。该选项在 LaunchOptions.ts 中被定义为 headless?: boolean | 'shell',与文档描述完全对应。

同理,启动时支持的浏览器、协议等参数统一定义在 LaunchOptions.tsLaunchOptions extends ConnectOptions)中,其中浏览器类型字段位于 LaunchOptions.ts

快速上手:安装与第一个脚本

两个 npm 包,如何选择

npm i puppeteer          # 完整方案:安装时自动下载配套的 Chrome
npm i puppeteer-core     # 轻量方案:只装库,不下载浏览器(需自带浏览器)
  • puppeteer:附带浏览器下载逻辑,对新手最友好,开箱即用;
  • puppeteer-core:适合你已有浏览器安装或需要精确控制浏览器版本的高级场景。

需要特别留意:现代包管理器(npm、pnpm、Yarn、Bun、Deno 等)默认会拦截依赖安装脚本。如果安装脚本被拦截,Puppeteer 将不会在安装阶段下载浏览器,运行时会因此报错。此时你可以手动执行:

npx puppeteer browsers install

或者把 "puppeteer" 加入 npm 配置的 "allowScripts" 中以放行安装脚本。本仓库 README.md 对此有完整说明。

第一个完整示例

下面的示例完整复现了仓库 README.md 的入门脚本——它演示了浏览器启动、页面导航、视口设置、键盘输入、ARIA 可访问性选择器、文本定位与页面求值等一整套核心 API:

import puppeteer from 'puppeteer';
// 或:import puppeteer from 'puppeteer-core';

// 启动浏览器并打开空白页
const browser = await puppeteer.launch();
const page = await browser.newPage();

// 导航到目标页面
await page.goto('https://developer.chrome.com/');

// 设置屏幕尺寸
await page.setViewport({width: 1080, height: 1024});

// 用键盘触发搜索菜单
await page.keyboard.press('/');

// 通过可访问名称定位输入框并填充
await page.locator('::-p-aria(Search)').fill('automate beyond recorder');

// 等待并点击第一条结果
await page.locator('.devsite-result-item-link').click();

// 用唯一文本定位标题元素并读取其文本
const textSelector = await page
  .locator('::-p-text(Customize and automate)')
  .waitHandle();
const fullTitle = await textSelector?.evaluate(el => el.textContent);

// 输出完整标题
console.log('The title of this blog post is "%s".', fullTitle);

await browser.close();

这段脚本同时展示了 Puppeteer 在设计上的一个独特亮点:::-p-aria / ::-p-text 这类 P 选择器。它们让定位器(Locator)不再只能依赖脆弱的 CSS 类名,而是可以直接面向 ARIA 可访问性角色或可见文本进行定位,使自动化代码更接近真实用户的操作语义。

在仓库中继续探索

本仓库是一个标准的 Puppeteer monorepo,各模块之间边界清晰,非常适合按需精读:

使用前提与边界

在把 Puppeteer 引入项目之前,有几个需要明确的前提与边界:

  • 浏览器依赖:使用 puppeteer 包时安装脚本会下载 Chrome;若用 puppeteer-core,则需要你自行准备浏览器二进制,并保证其存在(否则启动时会抛 Browser was not found 错误,BrowserLauncher.ts 中可以看到该检查逻辑);
  • 协议差异:WebDriver BiDi 尚未覆盖全部 CDP 特性,某些 API(如各种 emulation、Coverage、Tracing、拖拽专用 API 等)在 BiDi 下会抛 UnsupportedOperation,完整支持矩阵请参阅 docs/webdriver-bidi.md
  • 环境约束:具体支持哪些浏览器与系统版本,请以 supported-browsers.mdsystem-requirements.md 为准。

小结

一句话概括:Puppeteer 是一个把 Chrome/Firefox 的底层自动化协议(CDP 与 WebDriver BiDi)封装成直观 JavaScript 高层 API 的库——它默认无头运行、可按需切换有头或更轻量的 chrome-headless-shell,并覆盖表单与 UI 自动化、端到端测试、性能轨迹采集、扩展测试、截图/PDF、SPA 预渲染等几乎全部浏览器自动化场景。理解它的协议架构与默认行为(Firefox→BiDi、Chrome→CDP),是后续深入使用、排障乃至阅读其源码的第一步。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
594
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
916
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
516
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388