Puppeteer保存html,网页截图的两种实现方案:html2canvas & puppeteer

需求

上礼拜做了一个需求:将网页上的内容按顺序保存为图片,并上传至OSS返回URL给后端生成PPT。这里主要分享如何将网页的上的内容保存为图片。至于保存为图片之后的事,比如直接保存为本地,或者上传至服务器等,这里就不探索了。

实现

html2canvas

html2canvas是一个实现网页截图的库,允许你直接在用户浏览器上获取网页的截图或部分内容。屏幕截图是基于DOM的,因为它不做实际的屏幕截图,而是基于页面上可用的信息构建屏幕截图,因此它可能不是100%准确的。即,它只能正确地描述它所理解的属性,这意味着有许多CSS属性不起作用,比如动画。

如官网所说的,它的使用非常之简单。

npm install html2canvas

import html2canvas from 'html2canvas'

html2canvas(document.body).then(function(canvas) {

document.body.appendChild(canvas);

});

复制代码

实际上只要一行代码就能拿到转换好的canvas数据,await html2canvas(the element you want to convert)。

我的示例代码

click me to convert

below here are something that i want to take them to screenshot
尤雨溪说,看不懂文档你就回家去喂猪吧。IE说,你们都看我干嘛。

Vue logo

复制代码async shot() {

let ele = this.$refs["wrap"];

let canvas = await html2canvas(ele);

var img = canvas.toDataURL("image/png");

this.debugBase64(img);

},

// 这个方法会将渲染好的图片在新页面打开。

debugBase64(base64URL) {

var win = window.open();

win.document.write(

''

);

},

复制代码

效果如下图所示:0430cbc436ffaaab0e8046c568235f42.png

但实际上我在这里踩了大坑,我需要渲染的东西和公式有关,使用了mathjax渲染公式,其底层实现是svg,这导致我的公式无法被转换成canvas。(当然也有可能是其他原因导致的,欢迎指点)对此,就只好上绝招了,使用puppeteer。

puppeteer

之前有篇文章就写过使用这个node库将网页渲染成PDF并保存到本地,详见文章。渲染成PDF只是这个库的一个小功能,比如还可以用它截图。

screenshot是page实例中的一个方法,主要有以下配置项。可以全屏截图,也可以提供坐标和长宽对指定区域截图。e25ed3173f4ff2400fc7870d8331b92d.png

使用上倒是其次,安装puppeteer库倒是更麻烦点,因为这个需要下载一个完整的chrome应用,如果因为网络原因下载不了。可以在package.json中只安装其核心即puppeteer-core。在使用的时候自行配置本地的下载好chrome程序。这里不展开讲,可以搜索得到相关解决方案。以对知乎官网全屏截图为例。

const puppeteer = require("puppeteer-core");

async function getPic() {

const browser = await puppeteer.launch({

executablePath: "./chrome-win/chrome.exe",

});

const page = await browser.newPage();

await page.goto("https://zhihu.com", {

waitUntil: 'networkidle0',

});

await page.setViewport({ width: 1980, height: 1080 });

await page.content();

await page.screenshot({

path: "zhihu.png",

type: "jpeg",

quality: 100,

fullPage: true

});

await browser.close();

}

getPic();

复制代码

声明browser实例就配置了相对路径的本地应用,executablePath: "./chrome-win/chrome.exe"。有些单页面应用或许还要配置等待所有请求加载完毕,即waitUntil: 'networkidle0'。

截图效果如下:a5d1af8f1ccb49184e000b3ff3cc32a2.png

而如果要对指定区域截图,就要知道截图区域的坐标和长宽。一般来说,需要截图的部分都会有一个完整的DOM元素来渲染,如果不是,那就把它写在一个DOM元素内。

而对于如何获取一个DOM元素在页面上的位置,需要用到这几个DOM中的属性,offsetleft offsettop offsetWidth offsetheight。如果布局上有特殊的情况,那坐标的获取可能还需要特殊处理。

坐标拿到了,截图也跑通了。但似乎还有另一个问题:坐标只是存在于页面上,而需要坐标的是node端。如何构建其node和页面的桥梁将坐标传递给node。这就要用到page实例中的evaluate方法,该方法可以传递两个参数:pageFunction和args。前者是要在当前页面实例执行的方法,后者是要传递给当前方法的参数。用在这里就是,页面上将获取好的元素坐标信息放到window对象中,那在pageFunction中return window对象上的相关信息就好了。有时还需要将相关数据传递到页面供其使用,这个时候就是用第二个参数。代码如下:

const position = await page.evaluate(() => {

// eslint-disable-next-line no-undef

return window.elePostion

})

复制代码

拿到坐标后就可以依次截图了,截图可以保存为本地文件,也可以拿到该图片的buffer。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[网页截图的两种实现方案:html2canvas & puppeteer]http://www.zyiz.net/tech/detail-135645.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值