You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
networkidle2 - consider navigation to be finished when there are no more than 2 network connections for at least 500 ms. -- 来自 puppeteer 文档中关于 waitUtil 参数的描述
$ ldd node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome | grep not
libX11.so.6 => not found
libX11-xcb.so.1 => not found
libxcb.so.1 => not found
libXcomposite.so.1 => not found
libXcursor.so.1 => not found
libXdamage.so.1 => not found
libXext.so.6 => not found
libXfixes.so.3 => not found
libXi.so.6 => not found
libXrender.so.1 => not found
libXtst.so.6 => not found
libgobject-2.0.so.0 => not found
libglib-2.0.so.0 => not found
libnss3.so => not found
libnssutil3.so => not found
libsmime3.so => not found
libnspr4.so => not found
libcups.so.2 => not found
libdbus-1.so.3 => not found
libXss.so.1 => not found
libXrandr.so.2 => not found
libgio-2.0.so.0 => not found
libasound.so.2 => not found
libpangocairo-1.0.so.0 => not found
libpango-1.0.so.0 => not found
libcairo.so.2 => not found
libatk-1.0.so.0 => not found
libatk-bridge-2.0.so.0 => not found
libatspi.so.0 => not found
libgtk-3.so.0 => not found
libgdk-3.so.0 => not found
libgdk_pixbuf-2.0.so.0 => not found
$ google-chrome-unstable --version
Google Chrome 75.0.3745.4 dev
$ ldd node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome | grep not
google-chrome-unstable --version 正常输出版本号表示安装成功,再次检查 not found 的依赖项输出为空。
Puppeteer 截图及相关问题
Puppeteer 是 Headless Chrome 的 Node.js 封装。通过它可方便地对页面进行截图,或者保存成 PDF。
镜像的设置
因为其使用了 Chromium,其源在 Google 域上,最好设置一下 npm 从国内镜像安装,可解决无法安装的问题。
推荐在项目中放置
.npmrc
或.yarnrc
文件来进行镜像的设置,这样设置只针对项目生效,不影响其他项目,同时其他人不用重复在本地设置。这是一个整理好的
.npmrc
文件,如果使用的是 yarn,对应的.yarnrc
文件。也可通过如下命令从 GitHub gist 下载到项目中,截取页面
使用
page.screenshot()
API 进行截图的示例:实际应用中,你需要加上等待时间,以保证页面已经完全加载,否则截取出来的画面是页面半成品的样子。
通过
page.waitFor()
可让页面等待指定时间,const puppeteer = require('puppeteer'); puppeteer.launch().then(async browser => { const page = await browser.newPage(); await page.goto('https://example.com'); // 等待一秒钟 + await page.waitFor(1000); await page.screenshot({path: 'screenshot.png'}); await browser.close(); });
但这里无论你指定的时长是多少,都是比较主观的值。页面实际加载情况受很多因素影响,机器性能,网络好坏等。即页面加载完成是个无法预期的时长,所以这种方式不靠谱。我们应该使用另一个更加有保障的方式,在调用
page.goto()
时,可指定waitUntil
参数。const puppeteer = require('puppeteer'); puppeteer.launch().then(async browser => { const page = await browser.newPage(); await page.goto('https://example.com’,{ + waitUtil: 'networkidle2' }); await page.screenshot({path: 'screenshot.png'}); await browser.close(); });
networkidle2
会一直等待,直到页面加载后同时没有存在 2 个以上的资源请求,这个种状态持续至少 500 ms。此时再进行截图,是比较保险的了。
截图时还有个实用的参数
fullPage
,一般情况下也会搭配着使用,对整个页面进行截取。如果页面过长,超出了当前视窗(viewport),它会自动截取超出的部分,即截取结果是长图。这应该是大部分情况下所期望的。注意,其与
clip
参数互斥,即,如果手动指定了 clip 参数对页面进行范围的限定,则不能再指定fullPage
参数。针对页面中某个元素进行截取
如果你使用过 Chrome DevTool 中的截图命令,或许知道,其中有一个针对元素进行截取的命令。
Chrome DevTool 中对元素进行截图的命令
所以,除了对整个页面进行截取,Chrome 还支持对页面某个元素进行截取。通过
elementHandle .screenshot()
可针对具体元素进行截取。这就很实用了,能够满足大部分自定义的需求。大多数情况下,我们只对 body 部分感兴趣,通过只对 body 进行截取,就不用指定长宽而且自动排除掉 body 外多余的留白等。
其参数与
page.screenshot()
一样。需要注意的是,虽说一样,但其中是不能使用fullPage
参数的。因为针对元素进行图片截取已经表明是局部截图了,与fullPage
截取整个页面是冲突的,但它还是会自动滚动以截取完整的这个元素,fullPage
的优点没有丢掉。数据的返回
生成的图片可直接返回,也可保存成文件后返回文件地址。
其中,截图方法
page.screenshot([options])
的返回是<Promise<string|Buffer>>
,即生成的可能是 buffer 数据,也可以是base64 形式的字符串数据,默认为 Buffer 内容,通过设置encoding
参数为base64
便可得到字符串形式的截图数据。以 Koa 为例,binary 形式的 buffer 数据直接赋值给
ctx.body
进行返回,通过response.attachment
可设置返回的文件名。字符串形式时,需要注意拿到的并不是标准的图片 base64 格式,它只包含了数据部分,并没有文件类型部分,即
data:image/png;base64
,所以需要手动拼接后才是正确可展示的图片。如果你是以异步接口形式返回到前端,只需要将
"data:image/png;base64,${base64}"
这部分作为数据返回即可。当然,字符串形式下,仍然是可以返回成文件下载的形式的,
PDF 的生成
通过
page.pdf([options])
可将页面截取成 PDF 格式。一般 PDF 用于打印,所以默认以
print
媒体查询 (media query)的样式来截取。这里调用page.emulateMedia("screen")
显式指定环境为screen
而不是print
是为了得到更加接近于页面在浏览器中展示的效果。需要注意的是,如果页面中使用了背景图片,上面代码截取出来是看不到的。
截图 PDF 时背景图片未显示
需要设置截取时的
printBackground
参数为true
:await page.pdf({ path: "puppeteer.pdf", format: "A4", + printBackground: true });
修正后截图的 PDF 背景图片正常显示
一些问题
服务器字体文件问题
部署到全新的 Linux 环境时,大概率你会看到截来的图片中中文无法显示。
中文字体缺失的情况

那是因为系统缺少中文字体,Chromium 无法正常渲染。你需要安装中文字体,通过包管理工具或者手动下载安装。
服务器上 Chromium 无法启动的问题
在 Puppeteer 的 troubleshoting 文档 中有对应的解决方案。
一般是机器上缺少对应的依赖库,安装补上即可。Puppeteer 自带的 Chromium 是非常纯粹的,它不会安装除了自身作为浏览器外的其他东西。
通过
ldd
(List Dynamic Dependencies)命令可查看运行 Chromium 运行所需但缺少的 shared object dependencies。查看缺少的依赖项
那么多,一个个搜索(因为这里例出的名称不一定就是直接可用来安装的名称)安装多麻烦。所以需要用其他方法。
以 Debian 系统为例。
tips: 可通过
$ cat /etc/os-release
查看系统信息从而判断是什么系统。脚本安装
通过 troubleshoting 页面 Chrome headless doesn't launch 部分其列出的对应系统所需依赖中,将所有依赖复制出来组装成如下的命令执行:
通过安装 Chrome 来自动安装
直接安装一个非 Chromium 版本的 Chrome,它会把依赖自动安装上。
Chrome 是基于 Chromium 的发行版,包括
google-chrome-stable
,google-chrome-unstable
,google-chrome-beta
,安装任意一个都行。还是以 Debian 系统为例:
$ apt-get update && apt-get install google-chrome-unstable
如果直接执行上面的安装,会报错:
这是安装程序时的一个安全相关策略 ,需要先设置一下
apt-key
。$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
然后设置 Chrome 的仓库:
$ sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
再次执行安装便正常进行了。
安装时可以看到会提示所需的依赖项:
安装 Chrome 时的提示信息
按[Y] 确认即可。
有了这些依赖,Puppeteer 中的 Chromium 便可运行了。
$ google-chrome-unstable --version Google Chrome 75.0.3745.4 dev $ ldd node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome | grep not
google-chrome-unstable --version
正常输出版本号表示安装成功,再次检查not found
的依赖项输出为空。我们的目的只是安装依赖,所以装完后可移除 Chome。
apt-get remove google-chrome-unstable
时会自动列出其依赖项,就像安装时一样。后续如果机器上不再需要 Chromium 了可通过apt-get autoremove
来清理。卸载 Chrome 时的提示信息
sandbox 的问题
Linux 上 Puppeteer 启动 Chromium 时可能会看到如下的错误提示:
错误信息已经很明显,所以在启动时加上
--no-sandbox
参数即可。但考虑到安全问题,Puppeteer 是强烈不建议在无沙盒环境下运行,除非加载的页面其内容是绝对可信的。
如果需要设置在沙盒中运行,可参考文档中的两种方法。
相关资源
The text was updated successfully, but these errors were encountered: