使用node+puppeteer+express搭建截图服务

转载请注明出处https://www.cnblogs.com/funnyzpc/p/14222807.html

写在之前

一开始我们的需求是打开报表的某个页面然后把图截出来,然后调用企业微信发送给业务群

这中间我尝试了多种技术,比如html2imagepdf2imageselenium这些,这其中截图

比体验较好的也就selenium了,不过我们有些页面加载的时间较长,selenium似乎对html互操作性

也不是很完美(通过Thread.sleep并不能完美的兼容绝大多数报表),另外还有一个比较要命的

是Chromium渲染出来的页面似乎也有不同程度的问题(就是不好看),当然后面一个偶然的机会在

某不知名网站看到有网友用puppeteer来实现截图,遂~,一通骚操作就搭了一套出来(虽然最终方案并不是这个

,当然这是后话哈~),这里就拿出来说说哈~

准备

由于整个系统是基于node+express的web服务,puppeteer只是node的一个plugin,所以需要做的准备大致有下

  • 一台linux服务器,这里实用centos
  • node安装包(用于搭建node环境)
  • 字体文件

安装node环境

  • wget https://nodejs.org/dist/v14.15.3/node-v14.15.3-linux-x64.tar.xz
  • tar --strip-components 1 -xvJf node-v* -C /usr/local
  • npm config set registry https://registry.npm.taobao.org

安装pm2(用于守护node服务)

【注意:安装pm2前必须安装npm,如果只是非正式环境可以不用安装pm2】

安装字体

【这个其实很重要,我也绕了弯,原本以为改改字体编码就可以了,后来发现不是】

  • step1: 将window字体复制到linux下

    • windows: C:\Windows\Fonts
    • Linux: /usr/share/fonts/
  • step2: 建立字体索引信息并更新字体缓存
    • cd /usr/share/fonts/
    • mkfontscale
    • mkfontdir
    • fc-cache

准备代码

  • index.js
// 引入express module
// 引入puppeteer module
const express = require('express'),
app = express(),
puppeteer = require('puppeteer'); // 函数::页面加载监控
const waitTillHTMLRendered = async (page, timeout = 30000) => {
const checkDurationMsecs = 1000;
const maxChecks = timeout / checkDurationMsecs;
let lastHTMLSize = 0;
let checkCounts = 1;
let countStableSizeIterations = 0;
const minStableSizeIterations = 3; while(checkCounts++ <= maxChecks){
let html = await page.content();
let currentHTMLSize = html.length;
let bodyHTMLSize = await page.evaluate(() => document.body.innerHTML.length);
console.log('last: ', lastHTMLSize, ' <> curr: ', currentHTMLSize, " body html size: ", bodyHTMLSize);
if(lastHTMLSize != 0 && currentHTMLSize == lastHTMLSize)
countStableSizeIterations++;
else
countStableSizeIterations = 0; //reset the counter if(countStableSizeIterations >= minStableSizeIterations) {
console.log("Page rendered fully..");
break;
}
lastHTMLSize = currentHTMLSize;
await page.waitFor(checkDurationMsecs);
}
}; //创建一个 `/screenshot` 的route
app.get("/screenshot", async (request, response) => {
try {
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.setViewport({
width:!request.query.width?1600:Number(request.query.width),
height:!request.query.height?900:Number(request.query.height)
});
// 这里执行登录操作(非公共页面需要登录)
if(request.query.login && request.query.login=="true"){
// wait until page load
await page.goto('认证(登录)地址', { waitUntil: 'networkidle0' });
await page.type('#username', '登录用户名');
await page.type('#password', '登录密码');
// click and wait for navigation
await Promise.all([
page.click('#loginBtn'),
page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
}
await page.goto(request.query.url,{'timeout': 12000, 'waitUntil':'load'});
await waitTillHTMLRendered(page);
const image = await page.screenshot({fullPage : true,margin: {top: '100px'}});
await browser.close();
response.set('Content-Type', 'image/png');
response.send(image);
} catch (error) {
console.log(error);
}
});
// listener 监听 3000端口
var listener = app.listen(3000, function () {
console.log('Your appliction is listening on port ' + listener.address().port);
});
  • package.json
{
"name": "funnyzpc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

依赖安装

  • npm i --save puppeteer express

    [注意:如果安装失败 请检查是否更改为taobao源]

启动及管理

  • 直接使用node启动服务

    • node index.js
  • 使用pm2启动(如果安装了pm2)
    • 启动:pm2 start index.js
    • 进程:pm2 list
    • 删除:pm2 delete 应用ID

使用

由于以上代码已经对截图的加载做过处理的,所以无需在使用线程睡眠

同时代码也对宽度(width)和高度(height)做了处理,所以具体访问地址如下

http://127.0.0.1:3000/screenshot/?login=[是否登录true or false]&width=[页面宽度]&height=[页面高度]&url=[截图地址]

最后

虽然我们我们使用puppeteer能应对绝大多数报表,后来发现puppeteer对多组件图表存在渲染问题,所以就要求

提供商提供导出图片功能(用户页面导出非api),所以最终一套就是 http模拟登录+调用截图接口+图片生成监控+推送图片

好了,关于截图就分享到这里了,各位元旦节快乐哈~《@.@》

使用node+puppeteer+express搭建截图服务的更多相关文章

  1. node+express 搭建本地服务

    首先,得有node环境,其次建个项目 目录例如  酱紫! 再次 写server.js,当然你可以换个名字a.js .b.js.why.js随你喜欢 var express = require('exp ...

  2. 最近学习了Node,利用Express搭建了个人博客,总结下吧

    node+express+jade+mongodb搭建了一套个人博客,我来总结下这几个家伙的使用感受吧! [node] 成熟插件库众多,真的是只有你想不到,没有它做不到的.而且对于有前端JS基础的童鞋 ...

  3. Node.js+Express搭建博客系统基本环境安装

    1.下载安装node.js 官网下载地址:https://nodejs.org/en/download/ 2.安装express. 打开node命令行工具,在命令行中输入:npm install -g ...

  4. Node.js express模块 http服务

    var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('he ...

  5. Kubernetes实战 - 从零开始搭建微服务 1 - 使用kind构建一个单层架构Node/Express网络应用程序

    使用kind构建一个单层架构Node/Express网络应用程序 Kubernetes实战-从零开始搭建微服务 1 前言 准备写一个Kubernetes实战系列教程,毕竟cnblogs作为国内最早的技 ...

  6. Kubernetes实战 - 从零开始搭建微服务 - 1.5 提高可用性-发布多节点的Node/Express网络应用程序

    1.5 提高可用性-发布多节点的Node/Express网络应用程序 Kubernetes实战 - 从零开始搭建微服务 前言 在上一篇文章中,已经学习了如何简单地开发一个单层网络应用.[Kuberne ...

  7. 建立一个node.js服务器(使用express搭建第一个Web环境)

    一.官网下载node.js 下载地址:https://nodejs.org/en/download/ 根据向导,下一步安装就可以了! 二.使用express搭建Web环境 express是一个开源的n ...

  8. 使用 Node.js 搭建微服务网关

    目录 Node.js 是什么 安装 node.js Node.js 入门 Node.js 应用场景 npm 镜像 使用 Node.js 搭建微服务网关 什么是微服务架构 使用 Node.js 实现反向 ...

  9. 使用nodejs和express搭建http web服务

    目录 简介 使用nodejs搭建HTTP web服务 请求nodejs服务 第三方lib请求post 获取http请求的正文 Express和使用express搭建http web服务 express ...

随机推荐

  1. linux离线安装docker + docker-compose

    1 准备阶段(docker) 1.1 卸载旧版本 如果电脑上已经存在docker,需要先卸载可能存在的旧版本: 1. 删除某软件,及其安装时自动安装的所有包 sudo apt-get autoremo ...

  2. 第11.8节 Python正则表达式的重复匹配模式及元字符“?”、 “*”、 “+”功能介绍

    符号"?".""."+"这三个元字符修饰符在Python中都表示重复匹配的模式,即要求匹配的字符串满足重复次数的要求,但具体重复次数要求不同 ...

  3. 从零开始的sql注入学习(挖坑不填)

    首先,本人是小白,这篇文章也只是总结了一下大佬们的sql注入方法,要是有错,请各位大佬指出,以便学习. 虽然我是菜鸡,但是太过基础的sql注入问题也就不再重复的解释了.直接从常用的说起. 实战中常用的 ...

  4. 添加和读取Resources嵌入资源文件(例如.dll和.ssk文件)

    前言:有些程序运行的时候,可能调用外部的dll,用户使用时可能会不小心丢失这些dll,导致程序无法正常运行,因此可以考虑将这些dll嵌入到资源中,启动时自动释放.对于托管的dll,我们可以用打包软件合 ...

  5. Java-静态关键字Static&静态代码块

    静态成员变量:(static修饰变量) 如果一个成员变量使用了static关键字,那么这个变量不再属于对象自己,而是属于所在的类.多个对象共享同一份数据. 静态方法:(static修饰方法) 一旦使用 ...

  6. 2020高考倒计时!全屏向下滑动设计HTML源码

    全屏竖向滑动效果,自适应,多终端 全国高考倒计时,音乐自动播放. 背景图片:img目录下替换bg.jpg  背景音乐:audio目录下替换song.mp3 原本按照正常情况下每年的6月7.8日就是全国 ...

  7. 关于Switch Case的优化

    switch case虽然是代替if else而出现的,并不好维护,有时候使用switch还不如使用if else. 但没有别的东西能代替switch case了吗?答案当然是否定的,现在就有两种方式 ...

  8. 精尽Spring MVC源码分析 - HandlerMapping 组件(四)之 AbstractUrlHandlerMapping

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  9. Java读取系统默认时区

    工作中,遇到一个Java读取默认时区的问题,后来看了openjdk的源码,大致整理一下过程 public class Test { public void test(){ TimeZone.getDe ...

  10. el-collapse header修改

    先看一下修改后的效果 修改前el-collapse效果 对比一下 原版el-collapse的icon在右边,而我们UI设计是在最左边,而且右边还要加上此el-collapse-item的长度. 实现 ...