3、Puppeteer 基础:启动浏览器实例、打开新页面、页面导航与等待、截图与 PDF 生成
好,咱们正式开始动手了。
前面聊了那么多无头浏览器的概念和选型,说白了都是铺垫。真正干活,还得靠 Puppeteer。这一章我带你走一遍最核心的基础操作——启动浏览器、打开页面、导航等待、截图和 PDF。这些动作你以后每天都会用,就像吃饭喝水一样自然。
3.1 启动浏览器实例
Puppeteer 操作 Chrome,第一步永远是启动一个浏览器实例。我个人习惯把这个实例叫做 browser,它代表一个完整的浏览器进程。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true, // 无头模式,默认就是 true
args: ['--no-sandbox', '--disable-setuid-sandbox'] // 服务器上常用
});
console.log('浏览器启动成功');
// ... 后续操作
await browser.close();
})();
这里有个坑,我一开始就踩过。在 Linux 服务器上,如果不加 --no-sandbox,Puppeteer 会直接报错退出。为什么?因为默认的沙箱模式需要系统权限,而很多服务器环境没有。所以,服务器部署时,这两个参数几乎是标配。
browser.close()。否则进程会一直挂着,内存越吃越多。我曾经在线上忘记关,结果服务器 OOM 了,惨痛教训。
3.2 打开新页面
浏览器启动后,你得开个标签页才能干活。Puppeteer 里,每个标签页就是一个 Page 对象。
const page = await browser.newPage();
await page.goto('https://example.com');
就这么简单。但注意,newPage() 创建的是一个空白页,你需要用 goto() 告诉它去哪。我建议你每次创建新页面后,顺手设置一下视口大小,不然截图出来可能不是你想要的尺寸。
await page.setViewport({ width: 1280, height: 800 });
嗯,这个习惯我保持了很久。尤其是做截图对比测试时,视口不一致会导致误报。
3.3 页面导航与等待
导航,说白了就是让页面跳转。但网络环境复杂,你不能假设页面瞬间加载完。所以,等待是必须的。
3.3.1 基本导航
await page.goto('https://example.com', {
waitUntil: 'networkidle0' // 等待网络空闲
});
waitUntil 有几种选项:
| 选项 | 含义 |
|---|---|
load |
页面 load 事件触发后 |
domcontentloaded |
DOM 解析完成后 |
networkidle0 |
500ms 内没有网络请求 |
networkidle2 |
500ms 内网络请求数不超过 2 个 |
我个人最常用 networkidle0。为什么?因为很多页面会异步加载数据,光等 load 事件不够。你想想看,页面框架出来了,但数据还没到,这时候截图就是一张白板。
3.3.2 显式等待
有时候,导航完成不代表你要的元素出现了。这时候需要显式等待。
// 等待某个选择器出现
await page.waitForSelector('.content-loaded');
// 等待指定时间(不推荐,除非万不得已)
await page.waitForTimeout(3000);
waitForSelector 或 waitForFunction,别用固定延时。固定延时不稳定,网络慢时不够用,网络快时浪费时间。我见过太多人用 setTimeout 来等页面,结果测试时灵时不灵。
3.4 截图与 PDF 生成
这两个功能是 Puppeteer 的杀手锏。截图用于视觉验证,PDF 用于生成报告或存档。
3.4.1 截图
await page.screenshot({
path: 'screenshot.png',
fullPage: true // 截取整个页面,包括滚动部分
});
这里有个细节:fullPage: true 会把页面从头到尾截成一张长图。但有些页面无限滚动,你截不完。我建议在截图前先获取页面高度,做个限制。
const height = await page.evaluate(() => document.body.scrollHeight);
if (height > 10000) {
console.warn('页面过长,可能包含无限滚动');
}
另外,截图格式支持 PNG 和 JPEG。PNG 清晰但文件大,JPEG 体积小但有损。看场景选吧。
3.4.2 PDF 生成
PDF 生成是 Puppeteer 的独家优势。别的工具很难做到这么高质量的页面转 PDF。
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true // 打印背景颜色和图片
});
注意,PDF 生成时,页面会被渲染成打印样式。如果你发现 PDF 里少了某些元素,很可能是 CSS 里用了 @media screen 而不是 @media print。这时候可以模拟屏幕模式:
await page.emulateMediaType('screen');
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true
});
- 启动浏览器时,服务器环境记得加
--no-sandbox - 导航等待用
networkidle0,元素等待用waitForSelector - 截图用
fullPage: true但要小心无限滚动 - PDF 生成时注意 CSS 媒体类型
好了,这一章的基础操作就这些。你想想看,启动浏览器、打开页面、等待加载、截图或生成 PDF——这一套组合拳,已经能覆盖 80% 的自动化场景了。下一章我会讲更高级的页面交互,比如点击、输入、表单提交。到时候你会发现,Puppeteer 能干的事远不止这些。