Puppeteer 无头 Chrome 自动化
Puppeteer 是 Google 推出的 Node.js 库,提供了一套高级 API 来操控 Chrome 或 Chromium 浏览器。它可以在无头模式(Headless)下运行,非常适合在搬瓦工 VPS 上执行网页截图、PDF 生成、自动化测试和数据抓取等任务。Puppeteer 直接通过 DevTools Protocol 与浏览器通信,性能优异且功能丰富。
一、系统要求
- 操作系统:Ubuntu 20.04+(推荐 Ubuntu 22.04)。
- 内存:至少 1GB,推荐 2GB 以上。
- Node.js:16.0 以上版本。
二、安装 Node.js
apt update && apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install nodejs -y
node --version
npm --version
三、安装 Puppeteer
3.1 创建项目
mkdir -p /opt/puppeteer-project && cd /opt/puppeteer-project
npm init -y
3.2 安装 Puppeteer 及依赖
# 安装 Puppeteer(自带 Chromium)
npm install puppeteer
# 安装系统依赖
apt install -y libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 \
libxi6 libxtst6 libnss3 libcups2 libxss1 libxrandr2 \
libasound2 libpangocairo-1.0-0 libatk1.0-0 libatk-bridge2.0-0 \
libgtk-3-0 libgbm1 libdrm2
如果不想下载内置 Chromium,可以使用 puppeteer-core 并指定系统 Chrome 路径:
npm install puppeteer-core
四、基础用法
4.1 网页截图
创建 screenshot.js 文件:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'screenshot.png', fullPage: true });
console.log('截图已保存');
await browser.close();
})();
运行脚本:
node screenshot.js
4.2 生成 PDF
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.pdf({
path: 'output.pdf',
format: 'A4',
margin: { top: '20mm', right: '20mm', bottom: '20mm', left: '20mm' },
printBackground: true
});
console.log('PDF 已生成');
await browser.close();
})();
4.3 表单操作与页面交互
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.goto('https://example.com/login');
// 输入用户名和密码
await page.type('#username', 'myuser', { delay: 50 });
await page.type('#password', 'mypassword', { delay: 50 });
// 点击登录按钮并等待导航
await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle2' }),
page.click('#login-btn')
]);
console.log('登录后 URL:', page.url());
await browser.close();
})();
五、数据提取
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.goto('https://example.com');
// 提取页面数据
const data = await page.evaluate(() => {
const items = [];
document.querySelectorAll('.item').forEach(el => {
items.push({
title: el.querySelector('h2')?.textContent?.trim(),
link: el.querySelector('a')?.href,
price: el.querySelector('.price')?.textContent?.trim()
});
});
return items;
});
console.log(JSON.stringify(data, null, 2));
await browser.close();
})();
六、请求拦截
通过请求拦截可以屏蔽不必要的资源加载,提升页面打开速度:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
// 启用请求拦截
await page.setRequestInterception(true);
page.on('request', (req) => {
const resourceType = req.resourceType();
if (['image', 'font', 'stylesheet'].includes(resourceType)) {
req.abort();
} else {
req.continue();
}
});
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
const title = await page.title();
console.log('页面标题:', title);
await browser.close();
})();
七、多页面并发处理
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
];
const results = await Promise.all(urls.map(async (url) => {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
const title = await page.title();
await page.close();
return { url, title };
}));
console.log(results);
await browser.close();
})();
八、性能优化
在搬瓦工 VPS 上运行 Puppeteer,建议进行以下优化:
const browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage', // 避免 /dev/shm 空间不足
'--disable-accelerated-2d-canvas', // 禁用 GPU 加速
'--disable-gpu', // 禁用 GPU
'--single-process', // 单进程模式(低内存)
'--no-zygote', // 禁用 zygote 进程
'--js-flags=--max-old-space-size=256' // 限制内存
]
});
九、定时任务
将 Puppeteer 脚本配置为定时任务:
crontab -e
# 每小时执行一次截图任务
0 * * * * cd /opt/puppeteer-project && /usr/bin/node screenshot.js >> /var/log/puppeteer.log 2>&1
也可以使用 systemd 管理服务化的 Puppeteer 应用:
cat > /etc/systemd/system/puppeteer-app.service <<EOF
[Unit]
Description=Puppeteer Application
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/puppeteer-project
ExecStart=/usr/bin/node app.js
Restart=on-failure
RestartSec=10
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable puppeteer-app
systemctl start puppeteer-app
十、常见问题
Chromium 启动报错
VPS 上缺少图形库依赖是最常见的问题,确保已安装所有必要的系统包。也可以查看具体报错:
ldd $(find /opt/puppeteer-project/node_modules -name chrome -type f) | grep "not found"
超时错误
增加页面加载超时时间:
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 60000 // 60 秒
});
总结
Puppeteer 是在搬瓦工 VPS 上进行浏览器自动化的优秀选择,适用于截图监控、PDF 生成、自动化测试和数据采集等场景。建议选择内存 2GB 以上的方案。选购搬瓦工 VPS 请参考 全部方案,购买时使用优惠码 NODESEEK2026 可享受 6.77% 折扣。相关教程:Playwright 教程、Selenium 教程。