Puppeteer(中文翻译”操纵木偶的人”) 是 Google Chrome 团队官方的无界面(Headless)Chrome 工具,它是一个 Node
库,提供了一个高级的 API 来控制 DevTools协议上的无头版 Chrome 。也可以配置为使用完整(非无头)的 Chrome。Chrome
素来在浏览器界稳执牛耳,因此,Chrome Headless 必将成为 Web 应用自动化测试的行业标杆。使用 Puppeteer
,相当于同时具有 Linux 和 Chrome 双端的操作能力,应用场景可谓非常之多。早在 2017 年,就有写了大前端神器安利之 Puppeteer 等文章,用来讲述 Puppeteer
的作用;本文呢,旨在分享下使用过程中,需要注意的些事项。
避免新建无用的 tab 页
const puppeteer = require('puppeteer');
(async () => {
// 下面这一步启动浏览器时已经新建了一个空白 tab 页
// 所以 await browser.newPage(); 大多数时候是多余的
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.example.com/');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
上述 Demo 是常见的 Puppeteer 使用示例;但在实际运用过程中,将会出现一个问题:新建了一个多余的 Tab 页(空白页面),您可以做如下改变,即可解决问题:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
// 获取已有的第一个 tab 页
const page = (await browser.pages())[0]
await page.goto('https://www.example.com/');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
设置 User-Agent
有些网站也会根据浏览器发送到请求头判断访问者是真实用户还是爬虫,这时候我们就可以通过设置 User-Agent
来防止被网站限制访问,使用 page.setUserAgent()
即可。
await page.setUserAgent(
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
);
镜像的设置
Puppeteer 因为其使用了 Chromium,其源在 Google 域上,最好设置一下 npm,从国内镜像安装,可解决无法安装的问题。
推荐在项目中放置 .npmrc
或 .yarnrc
文件来进行镜像的设置,这样设置只针对项目生效,不影响其他项目,同时其他人不用重复在本地设置。
这是一个整理好的 .npmrc
文件,如果使用的是 yarn,对应的 .yarnrc
文件。也可通过如下命令从 GitHub gist 下载到项目中,
# .npmrc
npx pkgrc
# .yarnc
npx pkgrc yarn
针对页面中某个元素进行截取
如果你使用过 Chrome DevTool 中的截图命令,或许知道,其中有一个针对元素进行截取的命令。

所以,除了对整个页面进行截取,Chrome 还支持对页面某个元素进行截取。通过 elementHandle .screenshot()
可针对具体元素进行截取。
这就很实用了,能够满足大部分自定义的需求。在很多场景,我们或许只对 body 部分感兴趣,通过只对 body 进行截取,就不用指定长宽而且自动排除掉 body 外多余的留白等。
const puppeteer = require("puppeteer");
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
await page.goto("https://example.com", {
waitUtil: "networkidle2"
});
const element = await page.$("body");
await element.screenshot({
path: "screenshot.png"
});
});
其参数与 page.screenshot()
一样。需要注意的是,虽说一样,但其中是不能使用 fullPage
参数的。因为针对元素进行图片截取已经表明是局部截图了,与 fullPage
截取整个页面是冲突的,但它还是会自动滚动以截取完整的这个元素, fullPage
的优点没有丢掉。
必要时,使用代理
很多网站会记录访问者的 IP,并根据 IP 来判断访问者是真实的用户还是爬虫,如果发现是爬虫在获取数据,就会做出相应的限制措施。这时候我们就能使用代理来伪装我们的访问IP,从而防止被网站限制访问。
我们可以到一个免费的代理提供商网站(如 Hidester )去注册一个账户,获取代理服务器地址,然后启动puppeteer浏览器时传入启动参数 '--proxy-server=PROXY_SERVER_ADDRESS'
并且在打开的页面登录我们的账户即可使用代理。
我们可以使用 page.authenticate()
来自动登录我们的账户。
const puppeteer = require('puppeteer');
async function launch() {
const browser = await puppeteer.launch({
headless: true,
args: ['--proxy-server=PROXY_SERVER_ADDRESS']
});
console.log('Browser launched in headless mode!');
const page = await browser.newPage()
await page.authenticate({
username: 'USERNAME',
password: 'PASSWORD'
});
await browser.close();
}
launch().catch(e => {});
PDF 生成保留背景图片
一般 PDF 用于打印,所以默认以 print
媒体查询 (media query)的样式来截取。这里调用 page.emulateMedia("screen")
显式指定环境为 screen
而不是 print
是为了得到更加接近于页面在浏览器中展示的效果。需要注意的是,如果页面中使用了背景图片,需要设置截取时的 printBackground
参数为 true
:
await page.emulateMedia("screen");
await page.goto("https://www.google.com/chromebook/");
await page.pdf({
path: "puppeteer.pdf",
format: "A4",
+ printBackground: true
});
Linux 服务器字体文件问题
部署到 Linux 环境时,大概率你会看到截来的图片中中文无法显示。

那是因为系统缺少中文字体,Chromium 无法正常渲染。你需要安装中文字体,通过包管理工具,或者手动下载安装。
sudo apt-get install language-pack-zh*
sudo apt-get install chinese*
相关参考资料
您可能感兴趣的文章