使用node+puppeteer+express搭建截图服务
使用node+puppeteer+express搭建截图服务
写在之前
一开始我们的需求是打开报表的某个页面然后把图截出来,然后调用企业微信发送给业务群
这中间我尝试了多种技术,比如html2image,pdf2image、selenium这些,这其中截图
比体验较好的也就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.xztar --strip-components 1 -xvJf node-v* -C /usr/localnpm config set registry https://registry.npm.taobao.org
安装pm2(用于守护node服务)
【注意:安装pm2前必须安装npm,如果只是非正式环境可以不用安装pm2】
npm install pm2 -g- 其它操作请见https://pm2.keymetrics.io
安装字体
【这个其实很重要,我也绕了弯,原本以为改改字体编码就可以了,后来发现不是】
- 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搭建截图服务的更多相关文章
- node+express 搭建本地服务
首先,得有node环境,其次建个项目 目录例如 酱紫! 再次 写server.js,当然你可以换个名字a.js .b.js.why.js随你喜欢 var express = require('exp ...
- 最近学习了Node,利用Express搭建了个人博客,总结下吧
node+express+jade+mongodb搭建了一套个人博客,我来总结下这几个家伙的使用感受吧! [node] 成熟插件库众多,真的是只有你想不到,没有它做不到的.而且对于有前端JS基础的童鞋 ...
- Node.js+Express搭建博客系统基本环境安装
1.下载安装node.js 官网下载地址:https://nodejs.org/en/download/ 2.安装express. 打开node命令行工具,在命令行中输入:npm install -g ...
- Node.js express模块 http服务
var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('he ...
- Kubernetes实战 - 从零开始搭建微服务 1 - 使用kind构建一个单层架构Node/Express网络应用程序
使用kind构建一个单层架构Node/Express网络应用程序 Kubernetes实战-从零开始搭建微服务 1 前言 准备写一个Kubernetes实战系列教程,毕竟cnblogs作为国内最早的技 ...
- Kubernetes实战 - 从零开始搭建微服务 - 1.5 提高可用性-发布多节点的Node/Express网络应用程序
1.5 提高可用性-发布多节点的Node/Express网络应用程序 Kubernetes实战 - 从零开始搭建微服务 前言 在上一篇文章中,已经学习了如何简单地开发一个单层网络应用.[Kuberne ...
- 建立一个node.js服务器(使用express搭建第一个Web环境)
一.官网下载node.js 下载地址:https://nodejs.org/en/download/ 根据向导,下一步安装就可以了! 二.使用express搭建Web环境 express是一个开源的n ...
- 使用 Node.js 搭建微服务网关
目录 Node.js 是什么 安装 node.js Node.js 入门 Node.js 应用场景 npm 镜像 使用 Node.js 搭建微服务网关 什么是微服务架构 使用 Node.js 实现反向 ...
- 使用nodejs和express搭建http web服务
目录 简介 使用nodejs搭建HTTP web服务 请求nodejs服务 第三方lib请求post 获取http请求的正文 Express和使用express搭建http web服务 express ...
随机推荐
- Kafak探究之路- 内部结构小结
1.框架与工作流 2 内部结构 kafka的每个主题分区的数据在 first-0(主题名-分区号)文件夹下,保存 n组xxx.log文件与xxx.index文件.log文件存发送消息的元数据,每个大小 ...
- CSS初识- 选择器 &背景& 浮动& 盒子模型
# CSS初识-目标: > 1. 学会使用CSS选择器 > 2. 熟记CSS样式和外观属性 > 3. 熟练掌握CSS各种基础选择器 > 4. 熟练掌握CSS各种复合选择器 &g ...
- AcWing 276. I-区域
题目链接 设 \(0\) 为单调伸长, \(1\) 为单调伸短. 设 \(f[i][j][l][r][x(0 / 1)][y (0 / 1)]\) 为第 \(i\) 行,已经选出\(j\)个格子,第\ ...
- linux修改文件所属的用户组以及用户
linux修改文件所属的用户组以及用户 将文件夹从A用户(huangxf)目录复制B用户(zhenglf)目录,其中B没有sudo权限.将A的Downloads文件夹下的所有文件,复制到B的Docum ...
- vue+ springboot 分页(两种方式:sql分页 & PageHelper 分页)
方法一:sql分页 思路:使用数据库进行分页 前端使用element-ui的分页组件,往后台传第几页的起始行offest 以及每页多少行pageSize,后台根据起始行数和每页的行数可以算出该页的 ...
- JS怎么把for循环出来的东西放到一个数组里
var students=[ {name: "vehicleTravelLicenseCopyBack", id: "a1"}, {name: "ve ...
- Mysql性能优化专栏
1. 最大数据量 Mysql没有对单表的数据量大小做限制,单表的大小取决于操作系统对文件大小的限制. <阿里巴巴Java开发手册>中建议当单表的数据量大小超过500万行或者大于2GB时需 ...
- ubuntu 16.04 编译安装 python3.9
下载 python包 wget https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tgz 解压 tar zxf Python-3.9.1.tgz ...
- Spark-6-如何缓解消除数据倾斜
1 尽量避免数据源的数据倾斜 比如数据源是Kafka 以Spark Stream通过DirectStream方式读取Kafka数据为例.由于Kafka的每一个Partition对应Spark的一个Ta ...
- 多任务-python实现-Thread的基本使用(2.1.1)
@ 目录 1.多任务的概念 2.线程 1.多任务的概念 "多任务工作"指的是当前很普遍的工作状态,一个人同时处理多件事情,比如以下这个常见的画面:写一会报告,刷一下网页,查一下资料 ...