利用NODEJS+Puppeteer实现服务器保存网页为图片和PDF

本文适用于对docker,node有必定了解的童鞋node

Puppeteer简介

今年5月在github上建立的项目,属于比较新的chromium无头浏览器类库。git

Puppeteer在项目中的实际使用

基础安装

选用Puppeteer的主要缘由有两点,github

  • 1:GOOGLE官方维护,活跃度很高,我的以为前途光明。
  • 2:咱们的产品在chrome上适配最好。目前最新版本是0.13.0,咱们采用0.12.0版本,因0.13.0版本API作了一些变化没法知足咱们的需求。咱们截图时有以下两个必须解决的场景
    • 网站须要等待当前仪表盘全部查询都完成才能够进行截图操做
    • 咱们并不知道全部仪表盘发起的查询会查询多久结束

npm安装puppeteer时会从google一个网站上下载chromium,由于墙的缘由会下载失败。咱们采用的方式先设置环境变量chrome

set PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
复制代码

阻止install的时候自动下载,而后手工下载chromium后经过docker build打包成一个基础镜像。咱们在Dockerfile中From此镜像,而后再作后续操做。docker

npm instal puppeteer@0.12.0 --save
复制代码

如今可经过docker很快速的进行打包。最终打包后的image里/usr/src/node/包含node代码及chromium目录npm

基本操做

调用puppeteer

咱们手动指定chromium目录来运行。api

const browser = await puppteer.launch({
        args: ['--no-sandbox', '--disable-setuid-sandbox'],  // docker中运行须要加上这两个args
        executablePath: 'chromium/chrome', // 基础镜像已将chromium复制到/usr/src/node/chromium目录下
   });
复制代码

保存图片

经过URL打开网站浏览器

await page.goto(fullUrl, {
       waitUntil: 'networkidle',
       networkIdleTimeout: 15000,
       timeout: 240000
   });
复制代码

networkIdleTimeout: 15000参数表明当前页面网络处于idle状态至少15秒时导航完毕,避免导出的截图数据不全。
若是直接保存整个页面为图片或PDF是很简单的,有现成的API直接调用。但此次咱们只将某一区域保存为图片,网络

let rect = await page.evaluate(() => {
        const element = document.querySelector(
            '.class1'
        );  // 选择包含指定class属性的dom节点
        const { x, y, width, height } = element.getBoundingClientRect();
        return {
            left: x,
            top: y,
            width,
            height,
        };
    });
    await page.screenshot({
        path: imagePath,
        clip: {
            x: rect.x,
            y: rect.y,
            width: actualWidth,
            height: actualHeight
        }
    });
复制代码

能够在page.evaluate中操做页面元素,因此能够获取指定区域的长宽等信息。这样咱们只需截取那一区域便可。完整的API地址仍是请参阅github官方API文档dom

保存PDF

如上节所说,若是保存整个页面为PDF很简单,由于咱们只保存某一区域,然而保存pdf的API中没有相似page.screenshot中clip参数,个人处理方式就是将上一步保存的图片转为PDF便可。转换方式不少,我采用pdfkit类库实现。代码就不赘述,能够参考不少DEMO。

总结

由于咱们经过docker+CICD+devops打包部署node服务,puppeteer在docker中也有一些坑,好在官方给出了一系列解决方案。我在实际使用中仍是偶尔发生页面加载失败的状况,指望在将来版本会变得更增强大和稳定。

相关文章
相关标签/搜索