Puppeteer 快速上手:安装、浏览器下载机制与第一个自动化脚本
本文以仓库中 docs/index.md 这份官方首页文档为骨架,讲解 Puppeteer 的核心定位、
puppeteer与puppeteer-core的选型差异、安装阶段浏览器下载的完整机制,以及一段"搜索→定位→点击→读取结果"的可运行示例脚本,并穿插仓库源码级证据。读完本文,你将能独立完成 Puppeteer 的安装排错,并写出第一个可用的浏览器自动化程序。
Puppeteer 是一个提供高层 API 的 JavaScript 库,用于通过 DevTools Protocol(CDP) 或 WebDriver BiDi 协议控制 Chrome 或 Firefox 浏览器。当前仓库为 Puppeteer 25.8.0 时代的 monorepo(见 packages/puppeteer/package.json),在 Node.js 环境中默认以无头模式(headless,无可见 UI)运行浏览器,非常适合网页截图、PDF 生成、爬取 SPA 页面、自动化测试与端到端巡检等场景。
Puppeteer 是什么:一个库,两条协议,两款浏览器
从 docs/index.md 的定位描述出发,Puppeteer 的本质是"浏览器控制协议的封装层":
- 协议侧:同时支持 Chrome DevTools Protocol(CDP)与 WebDriver BiDi 两条通道,后者更接近标准化、跨浏览器一致的方向;
- 浏览器侧:官方面向 Chrome 与 Firefox 提供能力(Chrome 通过 CDP 或 BiDi,Firefox 通过 WebDriver BiDi);
- 运行形态:默认
launch()启动的是无头浏览器,无需图形界面即可工作。
在仓库的类结构上,这一"分层"非常直观:
- PuppeteerNode 继承自通用 Puppeteer 类,并额外承担"按需下载 / 解析可执行文件 / 裁剪缓存"等 Node 专属职责;
- packages/puppeteer-core/src/node/PuppeteerNode.ts 中
launch()会根据browser字段(chrome或firefox)路由到 ChromeLauncher 或 FirefoxLauncher。
也就是说,无论你最终面向哪款浏览器,"启动浏览器、开页面、执行动作、关闭"的用户侧心智模型完全一致。
安装:puppeteer 与 puppeteer-core 怎么选
官方文档给出的安装命令只有两条,但背后对应着两种完全不同的使用形态:
npm i puppeteer # 安装时会自动下载与版本匹配的 Chrome
npm i puppeteer-core # 纯库安装,不下载 Chrome,需要自行提供浏览器
两条命令的取舍可以这样理解:
| 对比项 | puppeteer |
puppeteer-core |
|---|---|---|
| 安装时是否下载浏览器 | 是(默认下载 Chrome for Testing 及 chrome-headless-shell) | 否 |
| 是否内置浏览器缓存管理 | 是 | 否 |
能否直接 launch() |
能,自动找到已下载浏览器 | 不能,需显式传入 executablePath 或 channel |
| 典型场景 | 快速起步、CI、本地自动化 | 复用系统 Chrome、远程/既有浏览器、嵌入式依赖 |
从源码看,二者在仓库内正是"装配层"与"内核层"的关系:puppeteer 包直接依赖 puppeteer-core(packages/puppeteer/package.json),并在 postinstall 钩子中执行 install.mjs 触发浏览器下载。仓库根目录的 puppeteer.config.js 也展示了 monorepo 自身的默认配置(三者都允许下载)。
现代包管理器默认拦截安装脚本的问题
随着 npm/pnpm/Yarn/Bun/Deno 等现代包管理器默认阻止依赖安装脚本,puppeteer 的 postinstall 很可能不会执行,结果是"包装好了但浏览器没下载",运行 launch() 时直接报运行时错误。官方文档给出了两条对策:
方案一:安装后手动补下浏览器
npx puppeteer browsers install
该命令读取当前 Puppeteer 安装对应的浏览器修订号并补齐下载,对应仓库中的 CLI 前缀命令 browsers(描述为 "Manage browsers of this Puppeteer installation",见 packages/puppeteer/src/node/cli.ts)。安装失败时日志还会引导你"先 npx puppeteer browsers clear 清理未完成安装的缓存再重试"(见 packages/puppeteer/src/node/install.ts)。
方案二:为包管理器放行安装脚本
例如使用 npm 时,在项目的 package.json 中把 "puppeteer" 加入 "allowScripts" 白名单,让 postinstall 正常执行自动下载。
除配置外,PUPPETEER_SKIP_DOWNLOAD=1 这类环境变量也能够在下载环节整体"喊停",错误信息中同样会提示这一点(见 install.ts)。
下载机制与版本选择源码侧速览
真正负责下载的是 install.ts 中的 downloadBrowsers():
- 读取合并后的配置(见 getConfiguration.ts);
- 对 Chrome、chrome-headless-shell、Firefox 分别判断
skipDownload,默认 Firefox 不下载(getConfiguration.ts中给 firefox 传了{skipDownload: true}的默认值,getConfiguration.ts); - 解析 buildId(配置里的
version优先,否则使用PUPPETEER_REVISIONS中记录的固定版本); - 通过
@puppeteer/browsers的install()下载到缓存目录,并打印xxx (buildId) downloaded to ...。
关于下载行为有两个值得记住的默认值:缓存目录默认是 ~/.cache/puppeteer;一旦配置或环境变量设置了 executablePath,系统会自动把 skipDownload 置为 true(getConfiguration.ts),即"你既然自带浏览器,就不再替你下载"。
配置从哪里来:配置文件搜索链与环境变量
虽然首页文档只介绍了最基础的安装,但理解配置读取顺序有助于解决"为什么没下载/为什么用了别的浏览器"这类问题。仓库实现中:
- 配置文件支持在
package.json的puppeteer字段以及多种.puppeteerrc.*/puppeteer.config.*/.config/...位置按序搜索(getConfiguration.ts); - 环境变量优先级高于配置文件,例如
PUPPETEER_BROWSER(默认浏览器,只接受chrome/firefox)、PUPPETEER_CACHE_DIR、PUPPETEER_EXECUTABLE_PATH、PUPPETEER_SKIP_DOWNLOAD、PUPPETEER_<BROWSER>_VERSION等(getConfiguration.ts); - 配置文件内容参考仓库根目录的 puppeteer.config.js:
/**
* @type {import("puppeteer").Configuration}
*/
export default {
chrome: { skipDownload: false },
['chrome-headless-shell']: { skipDownload: false },
firefox: { skipDownload: false },
};
完整可用的配置项说明见 docs/guides/configuration.md。
从零跑通第一个自动化脚本
官方首页文档提供了一段非常典型的"搜索引擎自动化"示例,这里逐段展开(含注释)以便直接复制运行:
import puppeteer from 'puppeteer';
// 也可以:import puppeteer from 'puppeteer-core';
// 1. 启动浏览器(默认 headless),并打开一个新空白页
const browser = await puppeteer.launch();
const page = await browser.newPage();
// 2. 导航到目标 URL
await page.goto('https://developer.chrome.com/');
// 3. 设置视口尺寸(屏幕分辨率,影响响应式布局与截图)
await page.setViewport({ width: 1080, height: 1024 });
// 4. 用键盘按下 '/' 键,唤起站点的搜索菜单
await page.keyboard.press('/');
// 5. 用可访问性(ARIA)名称定位搜索框并输入内容
await page.locator('::-p-aria(Search)').fill('automate beyond recorder');
// 6. 等待并点击第一个搜索结果
await page.locator('.devsite-result-item-link').click();
// 7. 用文本查询器定位包含唯一字符串的标题元素
const textSelector = await page
.locator('::-p-text(Customize and automate)')
.waitHandle();
const fullTitle = await textSelector?.evaluate(el => el.textContent);
// 8. 打印抓取到的标题
console.log('The title of this blog post is "%s".', fullTitle);
// 9. 关闭浏览器
await browser.close();
这个脚本把 Puppeteer 最核心的 API 串成了一条完整链路,值得逐一点明其用途:
puppeteer.launch():无参启动即使用默认 Chrome,等价于显式指定browser: 'chrome'(路由逻辑见 PuppeteerNode.ts);page.goto(url):页面级导航,等待页面完成加载后返回响应;page.setViewport({width, height}):等价于真实窗口尺寸,直接影响截图与移动端模拟,也可改用page.emulate()套用整套设备参数;page.keyboard.press('/'):Keyboard API 的常见用法,模拟真实键盘事件,同样支持type()/down()/up();page.locator('::-p-aria(Search)'):Puppeteer 的 Locator API,推荐在元素定位中使用。::-p-aria(Search)是 ARIA 角色/名称查询器,::-p-text(...)是文本查询器,二者与::-p-xpath()等同属于内置查询器体系;.waitHandle()与.evaluate():前者返回一个等待就绪的句柄(可能为undefined,因此原示例用了可选链),后者在页面上下文执行函数并回传结果——本例中直接取出标题的textContent。
Locator API 的另一层价值在于它把"等待元素出现 + 滚动入视口 + 可点击性检查 + 重试"等细节全部封装好,并原生支持 fill()、click()、hover()、wait() 等动作。所有 API 的逐项说明可在 docs/api/index.md 找到(如 locator、page.goto、keyboard)。
仓库 examples 目录中还提供了一批可直接学习的真实脚本,例如带中文注释思路的 search.js、screenshot.js 与跨浏览器示例 cross-browser.js,适合作为第一个脚本的进阶对照。
更进一步:MCP 生态与 WebMCP 实验 API
针对"AI 辅助浏览器自动化"方向,Puppeteer 生态有两层布局:
chrome-devtools-mcp:一个基于 Puppeteer 构建的 MCP(Model Context Protocol)服务端,面向浏览器自动化与调试场景,可直接接入支持 MCP 的 AI 编程助手,用于代替人类操作浏览器完成验证与排错;- WebMCP 实验 API:Puppeteer 自身暴露的实验性 WebMCP 能力,相关类型与 API 文档已沉淀在仓库中,例如 webmcp、webmcptool、webmcptoolcall.md 等。
如果你恰好需要将浏览器自动化能力注入 LLM/Agent 工作流,这两条路径是当前版本下的主要入口。
常见问题的定位思路
当脚本运行报错时,可按下述顺序自查:
Could not find Chrome/ 找不到浏览器:多半是安装脚本被包管理器拦截,先执行npx puppeteer browsers install手动补装;- 下载总是失败(网络/代理):安装时会自动把 npm 配置的
npm_config_proxy/npm_config_https_proxy/npm_config_no_proxy映射到系统代理环境变量(见 install.ts),可先检查本机 npm 代理配置是否可用; - 不想每次安装都下载:配置
skipDownload或设置PUPPETEER_SKIP_DOWNLOAD环境变量; - 想复用系统安装的浏览器:改用
puppeteer-core并显式传入executablePath或channel。
官方还提供了面向具体运行环境的排错资料:docs/troubleshooting.md(常见环境问题)与 docs/guides/docker.md(容器内运行),以及 docs/faq.md(高频疑问)。若在无头 Linux 服务器上使用,可对照 docker/README.md 中现成的镜像构建方案(含 docker/Dockerfile)起步,避免重复踩坑。
小结
回到 docs/index.md 给出的完整能力图景:Puppeteer 的价值不在协议细节,而在于把"跨 Chrome/Firefox、跨 CDP/BiDi"的复杂性收敛成一个稳定的高层 JS API。安装时理解 puppeteer 与 puppeteer-core 的分工、装好后跑通一个 Locator + 键盘 + 页面操作的示例,你就已经具备了把"手点浏览器"变成"代码驱动浏览器"的最小闭环能力;在此基础上再按需引入 MCP/WebMCP,即可把该能力扩展到 AI Agent 工作流中。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00