怎么利用 Node 生成海报?下面本篇文章给大家介绍一下使用 Node+Puppeteer 生成海报的方法,希望对大家有所帮助!
等待数据渲染完成再截图: page.content()
Java爬虫框架:Jvppeteer,java也可以使用爬虫哟_jvppeteer 点击页面_GJ_HQQ的博客-CSDN博客
怎么利用 Node 生成海报?下面本篇文章给大家介绍一下使用 Node+Puppeteer 生成海报的方法,希望对大家有所帮助!
之前文章写了一下前几天因为使用了 html2canvas 碰到了很多兼容性问题,差点提桶跑路。然后经过评论区大佬们指导,发现了一个操作简单,复用性高的海报生成方案—— Node+Puppeteer 生成海报 。
主要的设计思路为:访问生成海报的接口,接口通过 Puppeteer 去访问传入的地址,将对应的元素截图返回。
Puppeteer 生成海报相对于 Canvas 生成的优势有哪些:
- 没有浏览器兼容,平台兼容等问题。
- 代码复用性高,h5、小程序、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。
`
登录后复制
`
2. 创建一个截图模块
打开一个浏览器 ⇒ 打开一个标签页 ⇒ 截图 ⇒ 关闭浏览器
`
- 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 事件触发时。事件包括:
`
如果使用 networkidle0 的方案等待页面完成,会发现接口的响应时间会比较长, 因为 networkidle0 需要等待 500ms,真实业务场景下很多情况下不需要等待,所以可以封装一个延时器,可以自定义等待时间。比如我们的海报页只是渲染一个背景图跟一个二维码图片,页面触发 load 时已经加载完成了,不需要等待时间,可以传入 0 跳过等待时间。
`
如果这种方式不能满足,需要页面在某个时机通知 puppeteer 结束,还可以使用 page.waitForSelector(selector[, options]) 等待页面某个指定的元素出现。比如:页面执行完某个操作时,插入一个 的元素,puppereer 等待这个元素出现。
`
类似的方法共包括:
- 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 启动时还会开启很多不需要的功能,可以通过参数禁用某些启动项。
`
登录后复制
`
3. 复用浏览器
因为每次接口被调用都启动了一个浏览器,截图之后关闭了这个浏览器,造成了资源的浪费,并且启动浏览器也需要耗费时间。并且同时启动的浏览器过多,程序还会抛出异常。所以使用了连接池:启动多个浏览器,在其中一个浏览器下创建标签页打开页面,截图完成后只关闭标签页,保留浏览器。下一次请求过来时直接创建标签页,达到复用浏览器的目的。当浏览器使用次数达到一定数目或者一段时间内没有被使用时就关闭这个浏览器。 有大佬已经对 generic-pool 这个连接池进行了处理,我就直接拿来用了。
`
4. 优化接口防止图片重复生成
用同一组参数重复调用时每次都会开启一个浏览器进程去截图,可以使用缓存机制优化重复的请求。可以通过传入唯一的 key 作为标识位 (比如用户 id + 活动 id),将图片 base64 存入 redis 或者写入内存中。当接口被请求时先查看缓存里是否已经生成过,如果生成过就直接从缓存取。否则就走生成海报的流程。
结尾
这个方案目前已经开始在项目里试运行了,这对于我一个前端开发来说简直太友好了,再也不用在小程序里一步一步去绘制 canvas,不用考虑资源跨域,也不用考虑微信浏览器、各种自带浏览器的兼容问题。省下了时间可以让我写这篇文章。其次,我比较担心的还是性能问题,因为只有在分享的动作才会触发,并发较小,目前使用还未暴露出性能的问题,有了解的大佬们可以指导我一下可以进一步优化或者预防的点。
代码
完整代码查看:github
https://github.com/yuwuwu/markdown-code/tree/master/puppeteer%E6%88%AA%E5%9B%BE
更多 node 相关知识,请访问:nodejs 教程!!
以上就是浅析 Node 中怎么利用 Puppeteer 库生成海报(实现方案分享)的详细内容,更多请关注 php 中文网其它相关文章!