Puppeteer + Nodejs 通用全屏网页截图方案(一)基本功能

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

先来看看实现效果:

2022-06-22 10.38.49.gif

如上所示,此次实现的功能是输入网址后生成全屏截图,可用于生成图片版文章,也可以用做图片二维码海报的生成器,可以支持各种尺寸定义,下面讲解实现的一些技术细节。

实现截图

主要使用的是 puppeteer 这个库,最简单地实现一个网页截图,只需要几行代码即可:

const puppeteer = require('puppeteer') // 引入

    // 启动浏览器
    const browser = await puppeteer.launch({
      headless: false, // 本地测试先关掉无头模式
    })  
    // 创建一个页面
    const page = await browser.newPage()
    // 设置浏览器视窗
    page.setViewport({
      width: 300,
      height: 600,
    })
    // 输入网页地址
    await page.goto(url, { waitUntil: 'domcontentloaded' })
    // 开始截图,全屏截图的关键参数就是这个fullPage,页面会一直滚动到底
    await page.screenshot({ path: '{保存图片的路径}', fullPage: true })
    // 关闭浏览器
    await browser.close()

让网页接管截图动作

当我们使用浏览器截图方案作为内部业务方法使用的时候,为了保证生成图片的完整性,就需要等待异步操作执行完毕再开始截图,比如图片资源是否加载完成以及接口数据请求结果等判断,对于浏览器来说无能为力,而我们并不希望使用等待的方式来解决问题,而是让程序本身决定何时开始截图,这时我们可以通过 puppeteer 向页面注入一个全局方法,然后在目标页面中处理好资源的准备判断后,调用该方法,则可以实现页面对截图操作的控制。

c3d71e17-e9bf-49ae-9402-ccbd174bf5ce.png

//  puppeteer   注入全局方法
    
    await page.exposeFunction('loadFinishToInject', async () => {
      // console.log('-> 开始截图')
      await page.screenshot({ path, fullPage: true })
      // 关闭浏览器
      await browser.close()
    })
// 目标页面/业务页面/截图页面:

..... Some Preload Code Function ....

console.log('--> 可以开始截图')

    try {
     window.loadFinishToInject() // 触发截图方法
    } catch (err) {}

立即开始截图

通常情况下,我们可能只需要等待网页加载完成后就立即生成截图:

// 方法一:利用自带事件
await page.goto(url, { waitUntil: 'domcontentloaded' })
// console.log('-> 开始截图')
await page.screenshot({ path })
await browser.close()

waitUntil 说明:

  • load: window.onload 事件被触发时继续。
  • domcontentloaded: Domcontentloaded 事件触发时继续。
  • networkidle0: 在 500ms 内没有网络连接时(全部的request结束)则继续。
  • networkidle2: 500ms 内有不超过 2 个网络连接时就算成功(还有两个以下的request)则继续。
// 方法二:利用回调函数
    page.on('load', async () => {
        // 开始截图
        await page.screenshot({ path, fullPage: true })
        await browser.close()
    })

以上代码片段均是基于本地开发时的情况来写,后面将会介绍到服务器上部署的一些问题。

本服务默认使用Express作为框架,不展开介绍,下一篇文章将讲解一些常用参数的实现方法。

猜你喜欢

转载自juejin.im/post/7111875693255852062