返回顶部
首页 > 资讯 > 前端开发 > VUE >Node中如何用Puppeteer库生成海报
  • 593
分享到

Node中如何用Puppeteer库生成海报

2024-04-02 19:04:59 593人浏览 泡泡鱼
摘要

这篇文章主要介绍“node中如何用Puppeteer库生成海报”,在日常操作中,相信很多人在Node中如何用Puppeteer库生成海报问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大

这篇文章主要介绍“node中如何用Puppeteer库生成海报”,在日常操作中,相信很多人在Node中如何用Puppeteer库生成海报问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node中如何用Puppeteer库生成海报”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Node中如何用Puppeteer库生成海报

之前文章写了一下前几天因为使用了 html2canvas 碰到了很多兼容性问题,差点提桶跑路。然后经过评论区大佬们指导,发现了一个操作简单,复用性高的海报生成方案—— Node+Puppeteer生成海报

主要的设计思路为:访问生成海报的接口,接口通过Puppeteer去访问传入的地址,将对应的元素截图返回。

Puppeteer 生成海报相对于 Canvas 生成的优势有哪些:

  • 没有浏览器兼容,平台兼容等问题。

  • 代码复用性高,h6、小程序、app的生成海报服务都可以使用。

  • 优化操作空间更大。因为改成了接口生成海报的形式,可以使用各种服务端的方式去优化响应速度,比如:加服务器、加缓存

puppeteer介绍

Puppeteer 是一个 nodejs 库,它提供了一个高级 api 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行即“无头”模式,但是可以通过修改配置 headless:false 运行“有头”模式。 在浏览器中手动执行的绝大多数操作都可以使用 Puppeteer 来完成! 下面是一些示例:

  • 生成页面 pdf或者截图。

  • 抓取 SPA(单页应用)并生成预渲染内容(即“SSR”(服务器端渲染))。

  • 自动提交表单,进行 UI 测试,键盘输入等。

  • 创建一个时时更新的自动化测试环境。 使用最新的 javascript 和浏览器功能直接在最新版本的Chrome中执行测试。

  • 捕获网站的 timeline trace,用来帮助分析性能问题。

  • 测试浏览器扩展。

方案实现

1. 写一个简单的接口

Express 是一个简洁而灵活的 node.js WEB应用框架。使用express写一个简单的node服务,定义一个接口,接收截图所需的配置项传递给puppeteer。

const express = require('express')
const createError = require("Http-errors")
const app = express()
// 中间件--JSON化入参
app.use(express.json())
app.post('/api/getShareImg', (req, res) => {
    // 业务逻辑
})
// 错误拦截
app.use(function(req, res, next) {
    next(createError(404));
});
app.use(function(err, req, res, next) {
    let result = {
        code: 0,
        msg: err.message,
        err: err.stack
    }
    res.status(err.status || 500).json(result)
})
// 启动服务监听7000端口
const server = app.listen(7000, '0.0.0.0', () => {
    const host = server.address().address;
    const port = server.address().port;
    console.log('app start listening at http://%s:%s', host, port);
});

2. 创建一个截图模块

打开一个浏览器 => 打开一个标签页 => 截图 => 关闭浏览器

const puppeteer = require("puppeteer");

module.exports = async (opt) => {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.Goto(opt.url, {
            waitUntil: ['networkidle0']
        });
        await page.setViewport({
            width: opt.width,
            height: opt.height,
        });
        const ele = await page.$(opt.ele);
        const base64 = await ele.screenshot({
            fullPage: false,
            omitBackground: true,
            encoding: 'base64'
        });
        await browser.close();
        return 'data:image/png;base64,'+ base64
    } catch (error) {
        throw error
    }
};
  • puppeteer.launch([options]):启动一个浏览器

  • browser.newPage():创建一个标签页

  • page.goto(url[, options]):导航到某个页面

  • page.setViewport(viewport):制定打开页面的窗口

  • page.$(selector):元素选择

  • elementHandle.screenshot([options]):截图。其中encoding属性可以指定返回值是base64或Buffer

  • browser.close():关闭浏览器及标签页

3. 优化

1. 请求时间优化

page.goto(url[, options]) 方法的配置项 waitUntil 表示什么状态下算执行完毕, 默认是load事件触发时。事件包括:

 await page.goto(url, {
     waitUntil: [
         'load', //页面“load” 事件触发
         'domcontentloaded', //页面 “DOMcontentloaded” 事件触发
         'networkidle0', //在 500ms 内没有任何网络连接
         'networkidle2' //在 500ms 内网络连接个数不超过 2 个
     ]
 });

如果使用 networkidle0 的方案等待页面完成,会发现接口的响应时间会比较长, 因为 networkidle0 需要等待500ms,真实业务场景下很多情况下不需要等待,所以可以封装一个延时器,可以自定义等待时间。比如我们的海报页只是渲染一个背景图跟一个二维码图片,页面触发 load 时已经加载完成了,不需要等待时间,可以传入0跳过等待时间。

 const waitTime = (n) => new Promise((r) => setTimeout(r, n));
 //省略部分代码
 await page.goto(opt.url);
 await waitTime(opt.waitTime || 0);

如果这种方式不能满足,需要页面在某个时机通知puppeteer结束,还可以使用 page.waitForSelector(selector[, options]) 等待页面某个指定的元素出现。比如:页面执行完某个操作时,插入一个 id="end" 的元素,puppereer 等待这个元素出现。

 await page.waitForSelector("#end")

类似的方法共包括:

  • page.waitForXPath(xpath[, options]):等待 xPath 对应的元素出现在页面中。

  • page.waitForSelector(selector[, options]):等待指定的选择器匹配的元素出现在页面中,如果调用此方法时已经有匹配的元素,那么此方法立即返回。

  • page.waitForResponse(urlOrPredicate[, options]):等待指定的响应结束。

  • page.waitForRequest(urlOrPredicate[, options]):等待指定的响应出现。

  • page.waitForFunction(pageFunction[, options[, ...args]]):等待某个方法执行。

  • page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]]):此方法相当于上面几个方法的选择器,根据第一个参数的不同结果不同,比如:传入一个string类型,会判断是不是xpath或者selector,此时相当于waitForXPath或waitForSelector。

2. 启动项优化

Chromium启动时还会开启很多不需要的功能,可以通过参数禁用某些启动项。

    const browser = await puppeteer.launch({
        headless: true,
        slowMo: 0,
        args: [
            '--no-zygote',
            '--no-sandbox',
            '--disable-gpu',
            '--no-first-run',
            '--single-process',
            '--disable-extensions',
            "--disable-xss-auditor",
            '--disable-dev-shm-usage',
            '--disable-popup-blocking',
            '--disable-setuid-sandbox',
            '--disable-accelerated-2d-canvas',
            '--enable-features=NetworkService',
        ]
    });

3. 复用浏览器

因为每次接口被调用都启动了一个浏览器,截图之后关闭了这个浏览器,造成了资源的浪费,并且启动浏览器也需要耗费时间。并且同时启动的浏览器过多,程序还会抛出异常。所以使用了连接池:启动多个浏览器,在其中一个浏览器下创建标签页打开页面,截图完成后只关闭标签页,保留浏览器。下一次请求过来时直接创建标签页,达到复用浏览器的目的。当浏览器使用次数达到一定数目或者一段时间内没有被使用时就关闭这个浏览器。 有大佬已经对generic-pool这个连接池进行了处理,我就直接拿来用了。

const initPuppeteerPool = () => {
 if (global.pp) global.pp.drain().then(() => global.pp.clear())
 const opt = {
   max: 4,//最多产生多少个puppeteer实例 。
   min: 1,//保证池中最少有多少个puppeteer实例存活
   testOnBorrow: true,// 在将实例提供给用户之前,池应该验证这些实例。
   autostart: false,//是不是需要在池初始化时初始化实例
   idleTimeoutMillis: 1000 * 60 * 60,//如果一个实例60分钟都没访问就关掉他
   evictionRunIntervalMillis: 1000 * 60 * 3,//每3分钟检查一次实例的访问状态
   maxUses: 2048,//自定义的属性:每一个 实例 最大可重用次数。
   validator: () => Promise.resolve(true)
 }
 const factory = {
   create: () =>
     puppeteer.launch({
       //启动参数参考第二条
     }).then(instance => {
       instance.useCount = 0;
       return instance;
     }),
   destroy: instance => {
     instance.close()
   },
   validate: instance => {
     return opt.validator(instance).then(valid => Promise.resolve(valid && (opt.maxUses <= 0 || instance.useCount < opt.maxUses)));
   }
 };
 const pool = genericPool.createPool(factory, opt)
 const genericAcquire = pool.acquire.bind(pool)
 // 重写了原有池的消费实例的方法。添加一个实例使用次数的增加
 pool.acquire = () =>
   genericAcquire().then(instance => {
     instance.useCount += 1
     return instance
   })

 pool.use = fn => {
   let resource
   return pool
     .acquire()
     .then(r => {
       resource = r
       return resource
     })
     .then(fn)
     .then(
       result => {
         // 不管业务方使用实例成功与后都表示一下实例消费完成
         pool.release(resource)
         return result
       },
       err => {
         pool.release(resource)
         throw err
       }
     )
 }
 return pool;
}
global.pp = initPuppeteerPool()

4. 优化接口防止图片重复生成

用同一组参数重复调用时每次都会开启一个浏览器进程去截图,可以使用缓存机制优化重复的请求。可以通过传入唯一的key作为标识位(比如用户id+活动id),将图片base64存入Redis或者写入内存中。当接口被请求时先查看缓存里是否已经生成过,如果生成过就直接从缓存取。否则就走生成海报的流程。

到此,关于“Node中如何用Puppeteer库生成海报”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: Node中如何用Puppeteer库生成海报

本文链接: https://lsjlt.com/news/88353.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Node中如何用Puppeteer库生成海报
    这篇文章主要介绍“Node中如何用Puppeteer库生成海报”,在日常操作中,相信很多人在Node中如何用Puppeteer库生成海报问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大...
    99+
    2024-04-02
  • Node.js中如何使用Puppeteer库
    这篇文章主要讲解了“Node.js中如何使用Puppeteer库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Node.js中如何使用Puppeteer库”...
    99+
    2024-04-02
  • 如何利用node生成word文档
    这篇“如何利用node生成word文档”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何利...
    99+
    2024-04-02
  • 如何正确的使用puppeteer库
    如何正确的使用puppeteer库,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.初始化项目注: 这里我们会使用到 es6/7 的新特性...
    99+
    2024-04-02
  • 浅谈java如何生成分享海报工具类
    # 前言 例如:生成分享海报,比如注册扫二维码登录.分享商品海报等!本博文是基于springboot工程得! 一、使用步骤 1.导入pom依赖和上传图片到工程 代码如下(示例):...
    99+
    2024-04-02
  • 利用Matlab一键生成工地海报特效
    目录1.使用效果2.图片准备和导入3.图像倾斜4.扭曲置换5.正交叠底6.缘修整(抠图)7.背景图像替换8.完整代码1.使用效果 这篇的本质还是扭曲置换,其实看过前面几篇文章的应...
    99+
    2024-04-02
  • 拿来就用的Java海报生成器ImageCombiner(一)
    背景 如果您是UI美工大师或者PS大牛,那本文一定不适合你;如果当您需要自己做一张海报时,可以立马有小伙伴帮您实现,那本文大概率也不适合你。但是,如果你跟我一样,遇上到以下场景,最近公司上了不少传播方面的需求,需要合成各种营销图片。...
    99+
    2023-09-05
    java Powered by 金山文档
  • 使用canvas怎么生成带二维码的海报
    今天就跟大家聊聊有关使用canvas怎么生成带二维码的海报,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。图片不显示绘制渲染的时候图像不显示:是因为图片异步加载,所以canvas的操作...
    99+
    2023-06-09
  • 如何使用awrrpt.sql 生成AWR报告
    本篇内容主要讲解“如何使用awrrpt.sql 生成AWR报告”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用awrrpt.sql 生成AWR报告”吧!使...
    99+
    2024-04-02
  • .NET如何生成数据库
    这篇文章给大家分享的是有关.NET如何生成数据库的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。开篇语本文主要是回顾下从项目创建到生成数据到数据库(代码优先)的全部过程。采用EFCore作为ORM框架。本次示例环境...
    99+
    2023-06-15
  • vue3如何将html元素变成canvas(海报生成),进行图片保存/截图
    目录将html元素变成canvas(海报生成),进行图片保存/截图使用html2canvas将页面转化为图片将html元素变成canvas(海报生成),进行图片保存/截图 // 网页...
    99+
    2024-04-02
  • 怎么利用Matlab一键生成工地海报特效
    本篇内容介绍了“怎么利用Matlab一键生成工地海报特效”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.使用效果2.图片准备和导入首先m文...
    99+
    2023-06-29
  • 怎么用jquery canvas生成带有二维码的海报
    本篇内容主要讲解“怎么用jquery canvas生成带有二维码的海报”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用jquery canvas生成带有二维码的海报”吧!具体内容如下需求:点...
    99+
    2023-06-25
  • 如何在Python中使用Numpy库生成二维码?
    二维码是现代社会中常见的一种二维条码,它可以存储大量的信息,被广泛应用于商品管理、物流追踪、移动支付等领域。在Python中,我们可以使用Numpy库生成二维码,下面我们就来看看如何实现。 首先,我们需要安装qrcode库,它是一个用于生成...
    99+
    2023-07-21
    二维码 numpy http
  • unittest如何生成测试报告
    小编给大家分享一下unittest如何生成测试报告,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.把测试案例的结果写入文件在测试套件中,修改用于执行测试用例集的...
    99+
    2023-06-02
  • php如何生成报错日志
    本篇内容主要讲解“php如何生成报错日志”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php如何生成报错日志”吧!一、php.ini配置文件设置首先,我们需要找到php.ini文件,它通常位于P...
    99+
    2023-07-05
  • 如何使用pythonwasmtime调用rust生成的wasm库
    目录安装rust target wasm32-wasi编写rust库将rust库编译为wasm字节码安装python wasmtime库参考链接本文介绍了使用python wasmt...
    99+
    2023-01-04
    python wasmtime调用rust生成的wasm库 python wasmtime调用wasm库
  • 如何在 Golang 中使用第三方库生成随机数?
    在 go 中生成随机数时,math/rand 标准库提供基本功能。对于更复杂的需求,可以使用第三方库。github.com/bxcodec/faker 提供了生成随机数据的功能,包括:f...
    99+
    2024-05-13
    golang 随机数 git 标准库
  • PHP中token如何生成
    这篇文章主要为大家展示了“PHP中token如何生成”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PHP中token如何生成”这篇文章吧。php token的生成接口特点汇总:因为是非开放性的,...
    99+
    2023-06-20
  • db_load如何生成数据库文件
    这篇文章主要介绍 db_load如何生成数据库文件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!保存虚拟帐号和密码的文本文件无法被系统帐号直接调用。我们需要使用db_load 命令生...
    99+
    2024-04-02
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作