Puppeteer:94,300 个 GitHub Stars
Puppeteer 是一个用于无头 Chrome 和 Firefox 自动化的 Node.js 库,支持 Docker、GitHub Actions、Jest、Mocha、TypeScript。涵盖 puppeteer Docker 部署、生产环境上线、浏览器自动化教程和 CI/CD 集成。
- ⭐ 7366
- Python
- Apache-2.0
- 更新于 2026-05-19
LazyDocker:51,092 个 GitHub Stars • Grafana:74,380 个 GitHub Stars — 2026 Docker 部署指南
简介 #
大规模跑浏览器自动化,意味着要跟 Chrome 崩溃、无头环境的内存泄漏,以及页面加载间不稳定的选择器较劲。Puppeteer 由 Google 的 Chrome DevTools 团队维护,提供了一套高层级的 Node.js API,通过 DevTools Protocol 和 WebDriver BiDi 控制 Chrome 和 Firefox。凭借 94,300 个 GitHub Star、540+ 贡献者和每周 490 万次 npm 下载量,它依然是需要在生产环境里做可靠、可编程浏览器控制的团队的首选库。
这篇 puppeteer 教程会带你走完一套完整的浏览器自动化配置——从跑通 puppeteer docker 部署到 CI/CD 集成——附带真实配置、性能数据和坦诚的权衡取舍。无论你是要生成 PDF、抓取 SPA,还是跑端到端回归测试,这些 puppeteer 生产环境模式都能直接用上。
Puppeteer 是什么? #
Puppeteer 是一个 Node.js 库,提供一套编程 API,通过 Chrome DevTools Protocol (CDP) 和 WebDriver BiDi 控制 Chrome、Chromium 和 Firefox。它默认以无头模式运行,适合服务器环境,但在需要调试时也能驱动可见(“有头”)浏览器窗口。这个项目在 2017 年发布首个公开版本,此后成长为一个横跨网页抓取、PDF 生成、截图自动化、无障碍测试和 CI/CD 流水线的生态系统。
puppeteer 包会在安装时自动打包 Chromium,而 puppeteer-core 省略了浏览器下载——这个区别在 Docker 等你自己提供 Chrome 二进制文件的受限环境里很重要。
Puppeteer 是怎么工作的 #


Puppeteer 通过 WebSocket 连接和浏览器通信。当你调用 puppeteer.launch() 时,这个库会启动一个开启了远程调试功能的 Chrome 或 Firefox 进程(监听本地端口),然后通过 DevTools Protocol 连接上它。这种直连方式避免了老式基于 WebDriver 的工具所需的 HTTP 往返开销。
关键架构概念:
- Browser(浏览器):一个正在运行的浏览器实例。你可以并行运行多个来实现隔离。
- Page(页面):相当于一个浏览器标签页。大多数自动化代码都在和 Page 对象打交道。
- Context(上下文):浏览器上下文提供一个隔离的会话——独立的 Cookie、localStorage 和缓存。可以理解为一个隐身窗口。
- CDP Session(CDP 会话):对 Chrome DevTools Protocol 的底层访问,用于网络拦截、性能追踪、覆盖率报告等高级场景。
从 v25.0.0(2026 年 5 月)开始,Puppeteer 改为仅支持 ESM 模块,最低 Node.js 版本要求提升到 22。这去掉了 CommonJS 支持,转而拥抱原生 ES 模块,与更广泛的 Node.js 生态保持一致。
安装与配置 #
在装有 Node.js 22+ 的机器上,本地安装 Puppeteer 用不了三分钟。
# 安装并打包 Chromium
npm install puppeteer
# 或者用 puppeteer-core,自己管理 Chrome
npm install puppeteer-core
用一个最小脚本验证安装:
// quickstart.mjs —— 验证 Puppeteer 能正常启动
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log(`Page title: ${title}`);
await browser.close();
运行它:
node quickstart.mjs
# 预期输出:Page title: Example Domain
对于自己独立管理 Chrome 的环境——Docker、AWS Lambda,或预装了 Chromium 的系统——用 puppeteer-core 并设置 executablePath:
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium',
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
Docker 部署 #
在 Docker 里跑 Puppeteer 能消除"在我机器上明明能跑"的问题,让开发、预发布和生产环境的部署保持一致。挑战在于 Chromium 需要特定的系统库——少装一个,浏览器就会报出难以理解的启动错误。
生产环境 Dockerfile:
# Dockerfile —— 搭配 Chromium 的 Node.js 22,用于 Puppeteer
FROM node:22-slim
# 安装 Chromium 依赖和字体
RUN apt-get update && apt-get install -y --no-install-recommends \
chromium \
fonts-liberation \
libappindicator3-1 \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcups2 \
libdbus-1-3 \
libdrm2 \
libgbm1 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libx11-xcb1 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
xdg-utils \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# 使用系统自带的 Chromium,跳过打包下载
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
# 创建非 root 用户以保证安全
RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
&& mkdir -p /home/pptruser/app \
&& chown -R pptruser:pptruser /home/pptruser
WORKDIR /home/pptruser/app
# 安装依赖
COPY package.json package-lock.json ./
RUN npm ci --production
# 拷贝应用代码
COPY src/ ./src/
USER pptruser
CMD ["node", "src/index.mjs"]
构建并运行:
docker build -t puppeteer-app .
docker run --rm -v $(pwd)/output:/home/pptruser/app/output puppeteer-app
本地开发用的 docker-compose.yml:
version: '3.8'
services:
puppeteer:
build: .
volumes:
- ./src:/home/pptruser/app/src
- ./output:/home/pptruser/app/output
environment:
- NODE_ENV=production
- PUPPETEER_ARGS=--no-sandbox --disable-setuid-sandbox --disable-dev-shm-usage
shm_size: '2gb'
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 1G
shm_size 这个设置至关重要。Chrome 用 /dev/shm 做共享内存,Docker 容器默认给的 64MB 在处理大页面时会导致崩溃。设为 2GB 能避免无头模式下的"Aw, snap"错误。

Docker 资源限制和 Chrome 参数,用于稳定的无头运行。
核心自动化模式 #
抓取动态内容 #
现代 SPA 会在初始 HTML 响应之后才加载内容。Puppeteer 会先等待选择器出现,再提取数据:
// scraper.mjs —— 从 JavaScript 渲染的页面提取数据
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.setViewport({ width: 1366, height: 768 });
await page.setUserAgent(
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36'
);
await page.goto('https://quotes.toscrape.com/js/', {
waitUntil: 'networkidle2',
timeout: 30000
});
// 等待动态内容渲染完成
await page.waitForSelector('.quote', { timeout: 10000 });
const quotes = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.quote')).map(el => ({
text: el.querySelector('.text')?.textContent?.trim(),
author: el.querySelector('.author')?.textContent?.trim(),
tags: Array.from(el.querySelectorAll('.tag')).map(t => t.textContent.trim())
}));
});
console.log(`Scraped ${quotes.length} quotes`);
await browser.close();
截图和 PDF 生成 #
Puppeteer 非常擅长从 HTML 渲染视觉产物——这在发票、报表和 Open Graph 卡片图生成场景中很常见:
// screenshot.mjs —— 全页截图和 PDF 导出
import puppeteer from 'puppeteer';
import fs from 'fs';
import path from 'path';
const OUTPUT_DIR = './output';
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
// 截图:全页 PNG
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({
path: path.join(OUTPUT_DIR, 'page.png'),
fullPage: true
});
// PDF:A4,带背景图形
await page.pdf({
path: path.join(OUTPUT_DIR, 'page.pdf'),
format: 'A4',
printBackground: true,
margin: { top: '1cm', right: '1cm', bottom: '1cm', left: '1cm' }
});
console.log('Screenshot and PDF saved to', OUTPUT_DIR);
await browser.close();
网络拦截与请求屏蔽 #
在抓取场景中,屏蔽不必要的资源能把页面加载时间缩短 40-60%:
// blocker.mjs —— 屏蔽图片和 CSS 以加快抓取速度
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
// 拦截并屏蔽图片/样式表/媒体请求
await page.setRequestInterception(true);
page.on('request', (req) => {
const block = ['image', 'stylesheet', 'font', 'media'];
if (block.includes(req.resourceType())) {
req.abort();
} else {
req.continue();
}
});
const start = Date.now();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
console.log(`Loaded in ${Date.now() - start}ms (resources blocked)`);
await browser.close();
与主流工具集成 #
GitHub Actions #
在每次 push 时自动截图或跑回归测试:
# .github/workflows/puppeteer.yml
name: Puppeteer CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
puppeteer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Puppeteer tests
run: npm test
env:
CI: true
PUPPETEER_ARGS: '--no-sandbox --disable-setuid-sandbox'
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: screenshots
path: output/*.png
Jest 测试框架 #
// jest.config.js
module.exports = {
testEnvironment: 'node',
testMatch: ['**/*.test.mjs'],
testTimeout: 30000,
globals: {
'ts-jest': { useESM: true }
}
};
// homepage.test.mjs —— Jest + Puppeteer 集成
import puppeteer from 'puppeteer';
describe('Homepage', () => {
let browser;
let page;
beforeAll(async () => {
browser = await puppeteer.launch({
headless: 'new',
args: (process.env.PUPPETEER_ARGS || '').split(' ').filter(Boolean)
});
page = await browser.newPage();
});
afterAll(async () => {
await browser.close();
});
test('page title is correct', async () => {
await page.goto('https://example.com');
const title = await page.title();
expect(title).toBe('Example Domain');
});
test('navigation loads within 3 seconds', async () => {
const start = Date.now();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
expect(Date.now() - start).toBeLessThan(3000);
});
});
TypeScript 配置 #
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"strict": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
// src/scraper.ts —— TypeScript 搭配 Puppeteer
import puppeteer, { Browser, Page } from 'puppeteer';
interface Product {
name: string;
price: string;
url: string;
}
async function scrapeProducts(url: string): Promise<Product[]> {
const browser: Browser = await puppeteer.launch({ headless: 'new' });
const page: Page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
const products: Product[] = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.product')).map(el => ({
name: el.querySelector('.name')?.textContent?.trim() || '',
price: el.querySelector('.price')?.textContent?.trim() || '',
url: el.querySelector('a')?.href || ''
}));
});
await browser.close();
return products;
}
const results = await scrapeProducts('https://example.com/products');
console.log(`Found ${results.length} products`);
Mocha 测试运行器 #
// .mocharc.cjs
module.exports = {
extension: ['mjs'],
spec: 'test/**/*.test.mjs',
timeout: 30000,
exit: true
};
// test/scraper.test.mjs —— Mocha + Puppeteer
import puppeteer from 'puppeteer';
import assert from 'assert';
describe('Scraper Suite', function() {
this.timeout(30000);
let browser;
before(async () => {
browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
});
after(async () => await browser.close());
it('should extract product data', async () => {
const page = await browser.newPage();
await page.goto('https://example.com');
const heading = await page.$eval('h1', el => el.textContent);
assert.strictEqual(heading, 'Example Domain');
await page.close();
});
});
性能基准测试 / 真实使用场景 #
独立基准测试显示,在以 Chrome 为核心的场景下,Puppeteer 依然占据强势位置:
| 指标 | Puppeteer | Selenium | Playwright | Cypress |
|---|---|---|---|---|
| 平均操作延迟 | < 1 秒 | 3-5 秒 | 1-2 秒 | 1-2 秒 |
| 配置耗时 | 10-15 分钟 | 2-4 小时 | 15-30 分钟 | 15-30 分钟 |
| 通过率(100 次运行) | 93% | 84% | 94% | 96% |
| 单实例内存占用 | 200-400MB | 300-500MB | 250-450MB | 400-600MB |
| 测试套件(50 个测试) | 顺序 2 分 55 秒 / 并行 48 秒 | 顺序 8 分 45 秒 / 并行 2 分 50 秒 | 顺序 3 分 20 秒 / 并行 52 秒 | 顺序 3 分 45 秒 / 并行 1 分 10 秒 |
| 每月维护成本 | 约 11 小时 | 约 16.5 小时 | 约 12 小时 | 约 10.5 小时 |
什么时候该选 Puppeteer 而不是其他方案:
- PDF 生成和截图流水线:Puppeteer 的
page.pdf()和page.screenshot()是浏览器自动化领域最成熟的 API。 - Chrome DevTools Protocol 访问:对于要构建开发者工具、性能分析器或覆盖率报告工具的团队,直接 CDP 访问是只有 Puppeteer 原生满足的需求。
- 大规模网页抓取:搭配 Bull 或 RabbitMQ 这样的任务队列,Puppeteer 能以极低开销每小时处理数千个 URL。
- 已有 Node.js 基础设施:如果你的后端已经是 TypeScript/JavaScript,引入 Puppeteer 不会带来任何新的运行时或语言。
进阶用法 / 生产环境加固 #
浏览器池管理 #
每个请求都启动一个新浏览器很浪费。连接池能复用浏览器实例:
// pool.mjs —— 带最大并发限制的可复用浏览器池
import puppeteer from 'puppeteer';
class BrowserPool {
constructor(maxBrowsers = 5) {
this.maxBrowsers = maxBrowsers;
this.pool = [];
this.queue = [];
}
async init() {
for (let i = 0; i < this.maxBrowsers; i++) {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
});
this.pool.push({ browser, inUse: false });
}
}
async acquire() {
const available = this.pool.find(b => !b.inUse);
if (available) {
available.inUse = true;
return available.browser;
}
return new Promise(resolve => this.queue.push(resolve));
}
release(browser) {
const entry = this.pool.find(b => b.browser === browser);
if (entry) {
entry.inUse = false;
if (this.queue.length > 0) {
const next = this.queue.shift();
entry.inUse = true;
next(entry.browser);
}
}
}
async close() {
await Promise.all(this.pool.map(b => b.browser.close()));
}
}
const pool = new BrowserPool(3);
await pool.init();
const browser = await pool.acquire();
const page = await browser.newPage();
await page.goto('https://example.com');
// …… 干活 ……
await page.close();
pool.release(browser);
优雅的错误处理与重试 #
生产环境的抓取任务会遇到网络超时、反爬检测和临时故障。用指数退避包装页面导航:
// retry.mjs —— 带指数退避的健壮导航
async function gotoWithRetry(page, url, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 30000
});
return;
} catch (err) {
if (attempt === maxRetries) throw err;
const delay = Math.pow(2, attempt) * 1000;
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
await new Promise(r => setTimeout(r, delay));
}
}
}
健康监控 #
在长期运行的服务中,监控浏览器进程健康状态,并重启崩溃的实例:
// health.mjs —— 浏览器进程的基础健康检查
async function isBrowserHealthy(browser) {
try {
const version = await browser.version();
return !!version;
} catch {
return false;
}
}
// 每 60 秒定期检查
setInterval(async () => {
for (const entry of pool.pool) {
const healthy = await isBrowserHealthy(entry.browser);
if (!healthy) {
console.warn('Unhealthy browser detected, restarting...');
await entry.browser.close();
entry.browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox'] });
entry.inUse = false;
}
}
}, 60000);
与其他方案对比 #
| 特性 | Puppeteer | Selenium | Playwright | Cypress |
|---|---|---|---|---|
| 主要语言 | JavaScript, TypeScript | Java, Python, C#, JS, Ruby | JS/TS, Python, Java, .NET | JavaScript, TypeScript |
| 浏览器支持 | Chrome, Chromium, Firefox | 所有主流 + 移动端 (Appium) | Chromium, Firefox, WebKit | Chromium, Edge, Firefox |
| 协议 | CDP, WebDriver BiDi | W3C WebDriver | CDP, WebDriver BiDi | 浏览器内执行 |
| 执行速度 | 极快 (< 1秒/操作) | 慢 (3-5秒/操作) | 快 (1-2秒/操作) | 快 (1-2秒/操作) |
| 内置测试运行器 | 无(用 Jest/Mocha) | 无(用外部工具) | 有 (playwright test) | 有 |
| 并行执行 | 手动配置 | Selenium Grid | 内置 worker | Cypress Cloud(付费) |
| PDF 生成 | 原生 (page.pdf) | 第三方 | 原生 | 第三方插件 |
| 移动端模拟 | Chrome 设备模拟 | 完整支持(通过 Appium) | 视口模拟 | 无 |
| 社区 / GitHub Star | 94,300 | 34,000 | 78,000 | 48,000 |
| 协议 | Apache-2.0 | Apache-2.0 | Apache-2.0 | MIT |
| 最适合 | 抓取、PDF、截图 | 企业、多语言场景 | 跨浏览器测试 | 前端开发者测试 |
选型建议: 如果你的工作以 Chrome 自动化为核心——抓取、PDF 生成、截图流水线,或 DevTools 集成——选 Puppeteer。如果你需要在单个测试套件里覆盖 Chromium、Firefox 和 WebKit 的跨浏览器测试,Playwright 能力更全面。对 Java/.NET 团队或传统企业环境来说,Selenium 依然是默认选择。Cypress 适合把开发者体验和可视化调试看得比原始执行速度更重要的 JavaScript 团队。
局限性 / 真实评估 #
Puppeteer 并不是每种浏览器自动化任务的最佳选择。投入使用前先考虑这些限制:
- 仅限 JavaScript:Puppeteer 是一个 Node.js 库。用 Python、Java 或 Go 的团队只能用
pyppeteer(非官方,更新滞后)或转向 Selenium/Playwright。 - 跨浏览器支持有限:虽然通过 WebDriver BiDi 支持 Firefox,但成熟度不如 Chrome 自动化。不支持 Safari 和 WebKit。如果跨浏览器测试是硬需求,Playwright 原生覆盖全部三种渲染引擎。
- 没有内置测试运行器:不像 Cypress 或 Playwright,Puppeteer 不自带断言、测试组织或报告工具,需要你自己搭配 Jest、Mocha 或 Vitest。
- 并行化需要手动实现:并行测试执行需要手动管理浏览器池或借助外部编排工具。对大型测试套件来说,Playwright 内置的 worker 模型更简单。
- 内存占用:每个 Chrome 实例消耗 200-400MB 内存。并发抓取数千个页面需要相当规模的基础设施或基于集群的方案。
- 反爬检测:现代网站用 Cloudflare、DataDome 和 PerimeterX 检测无头浏览器。仅靠 Puppeteer 本身绕不过这些系统——需要额外用上
puppeteer-extra-plugin-stealth之类的工具,且效果参差不齐。
常见问题 #
puppeteer 和 puppeteer-core 有什么区别? #
puppeteer 包会在安装时打包并下载 Chromium。puppeteer-core 包只包含 JavaScript API,期望你通过 executablePath 启动参数提供 Chrome 或 Chromium 可执行文件。在 Docker、CI/CD 流水线,以及自己管理浏览器二进制文件的环境里,用 puppeteer-core。
Puppeteer 支持 Firefox 吗? #
支持,自 2023 年起 Puppeteer 通过 WebDriver BiDi 协议支持 Firefox。不过 Firefox 支持的成熟度不如 Chrome 自动化。一些 CDP 专属功能,比如性能追踪和覆盖率报告,仅限 Chrome。如果生产工作负载要面向 Firefox,Playwright 可能提供更广泛的 API 对等能力。
怎么在 Docker 里以非 root 权限运行 Puppeteer? #
在 Dockerfile 里创建一个专属的非 root 用户,把它加入 audio 和 video 用户组,然后用 --no-sandbox 和 --disable-setuid-sandbox 参数运行 Chrome。本指南里的示例 Dockerfile 展示了完整配置。注意 --no-sandbox 会降低进程隔离性,但在容器化环境里,容器本身提供了安全边界,这个权衡是可以接受的。
Puppeteer 25 最低需要什么 Node.js 版本? #
Puppeteer v25.0.0 及之后的版本要求 Node.js 22 或更高。这个版本改成了仅支持 ESM 模块,不再支持 CommonJS 的 require()。如果你用的是 Node.js 18 或 20,安装 Puppeteer 25 前先升级,或者锁定在支持 Node.js 18+ 的 Puppeteer 24.x。
怎么降低 Puppeteer 生产部署的内存占用? #
用浏览器池限制并发 Chrome 实例数量,通过请求拦截屏蔽图片、CSS、字体等不必要的资源,用完页面立刻关闭,并设置 --disable-dev-shm-usage 参数,改用 /tmp 而不是 /dev/shm 做共享内存。在 Docker 里,把 shm_size 提高到至少 2GB,防止渲染进程崩溃。
Puppeteer 适合大规模网页抓取吗? #
搭配合适的基础设施,Puppeteer 能应对大规模抓取。一台 4GB 内存的机器上,单个 Node.js 进程能管理 3-5 个并发 Chrome 实例。要获得更高吞吐量,用消息队列(Redis、RabbitMQ、SQS)把工作分发到多个容器或虚拟机上。要注意很多网站会主动屏蔽无头浏览器,所以生产抓取流水线要把 Puppeteer 和代理轮换、指纹随机化结合起来使用。
Puppeteer 和 Playwright 在测试场景下比怎么样? #
Puppeteer 和 Playwright 师出同门——Playwright 团队最初就是在 Google 打造了 Puppeteer,后来才转到微软。Playwright 追加了跨浏览器支持(WebKit/Safari)、内置测试运行器、自动等待和移动设备模拟。以 Chrome 为核心的自动化和抓取选 Puppeteer。需要最广泛浏览器覆盖的跨浏览器端到端测试选 Playwright。
结语 #
对于需要以编程方式控制 Chrome 的团队,Puppeteer 依然是稳妥之选。它的 94,300 个 GitHub Star,加上 Chrome DevTools 团队的持续维护,标志着长期稳定性。在 PDF 生成、截图流水线和基于 Chrome 的抓取场景,这个库的 API 覆盖面无可匹敌。本指南中的 Docker 模式、浏览器池管理和重试逻辑,为生产环境提供了一套可用的基础方案。
行动清单:
- 克隆官方 Puppeteer 示例,把抓取模式适配到你的目标网站上。
- 用本指南中的 Dockerfile 构建镜像,在预发布环境里跑起来。
- 配置 GitHub Actions 工作流,在每次 PR 时自动截图或跑回归测试。
- 加入 dibi8 Telegram 群,分享你的 Puppeteer 部署经验,也能从其他跑大规模浏览器自动化的开发者那里获得帮助。
推荐的托管与基础设施 #
在把上面这些工具部署到生产环境之前,你需要靠谱的基础设施。以下两个是 dibi8 实际在用、并推荐的方案:
- DigitalOcean — 60 天 200 美元免费额度,覆盖 14+ 全球区域。独立开发者跑开源 AI 工具的默认选择。
- HTStack — 香港 VPS,大陆访问低延迟。dibi8.com 本身就托管在这家 IDC——生产环境实测过硬。
以上为联盟链接——不会让你多花一分钱,但能帮 dibi8.com 持续运营下去。
来源与延伸阅读 #
- Puppeteer 官方文档 — API 参考与指南
- Puppeteer GitHub 仓库 — 源码、issue、发布记录
- Puppeteer 更新日志 — 版本历史与破坏性变更
- Chrome DevTools Protocol — 底层协议文档
- Puppeteer Docker 示例 — 官方 Docker 配置
- WebDriver BiDi 规范 — 跨浏览器自动化标准
- Puppeteer vs Playwright 基准研究 — 独立性能对比
- Browserless.io Puppeteer 托管 — 托管式 Puppeteer 基础设施
💬 留言讨论