使用puppeteer生成pdf与截图
之前写过一篇 vue cli2 使用 wkhtmltopdf 踩坑指南,由于wkhtmltopdf对vue的支持并不友好,而且不支持css3,经过调研最终选择puppeteer,坑少,比较靠谱。
一、准备工作
- puppeteer中文文档: https://zhaoqize.github.io/puppeteer-api-zh_CN/#/
- node版本必须在10.18.1+以上
- 新建pdf.js
- 安装puppeteer
npm install puppeteer
(这里用的是15.0.1版本,测试没问题) - 需要生成pdf的html页面需要添加打印样式(不添加会导致背景色无法显示等问题)
html {
-webkit-print-color-adjust: exact;
}
- cd到pdf.js所在的文件夹执行node pdf.js
二、常用案例
这里直接提供一些常用的生成pdf案例,比较简单,直接复制就能用
1. 通过设置token下载pdf的最简单使用方式
直接执行 node pdf.js 即可
pdf.js
const puppeteer = require('puppeteer')
const token = 'kjjkheyJzdWIiOiIxMDAwMDAwMDAwMDAxMjM0'
async function printPDF() {
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.setExtraHTTPHeaders({'uniedu-sso-token': token})
await page.goto('https://test.web.moedu.net/aital-class-review-h5/#/reportDetail', {waitUntil: 'networkidle0'})
await page.pdf({ path: 'test.pdf', format: 'A4'})
await browser.close()
}
printPDF()
2. 通过html字符串生成pdf
pdf.js
const puppeteer = require('puppeteer')
const html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />·
<title>Document</title>
<style>
html {
line-height: 1.15;
-webkit-print-color-adjust: exact;
}
body {
margin: 0;
font-family: "Times New Roman",'宋体';
font-weight: 400;
}
</style>
</head>
<body>
<div>页面Dom</div>
</body>
</html>`
async function printPDF() {
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.setContent(html, {waitUntil: 'networkidle0'})
await page.pdf({ path: 'test.pdf', format: 'A4'})
await browser.close()
}
printPDF()
3. 简单封装node命令的形式并通过引入html文件生成pdf
首先需要安装 npm install minimist
这里的A3自定义了宽高,puppeteer也有自己默认的A3尺寸,具体详见官方文档page.pdf([options])
生成test.pdf可通过执行该命令 node pdf.js --format=A3 --htmlPath=./index.html --pdfPath=./test.pdf
const puppeteer = require('puppeteer')
const fs = require('fs')
const args = require('minimist')(process.argv.slice(2))
const format = args['format']
const htmlPath = args['htmlPath']
const pdfPath = args['pdfPath']
const pdfParams = {
'A3': {
path: pdfPath,
width: '420mm',
height: '297mm',
margin: {
right: '0.1cm',
}
},
'A4': {
path: pdfPath,
format: 'A4'
}
}
async function printPDF(format = 'A4') {
// 如果需要部署在服务端尽量加上这行参数
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox'], headless: true})
const page = await browser.newPage()
const htmlContent = fs.readFileSync(htmlPath, 'utf-8')
await page.setContent(htmlContent, { waitUntil: 'networkidle0' })
await page.pdf(pdfParams[format])
await browser.close()
}
printPDF(format)
4. 循环异步批量下载pdf
这里browser只需要打开一次就可以了,只需要每次跳转新页面下载pdf,这样可以不用频繁的开启关闭无头浏览器
const puppeteer = require('puppeteer')
const tokens = require('./tokens.json')
async function printPDF(page, token, index) {
console.log(`第${index + 1}份正在打印……`)
await page.goto('https://baidu.com', {waitUntil: 'networkidle0'});
await page.pdf({ path: `./pdf/node${index + 1}.pdf`, format: 'A4'})
console.log(`第${index + 1}份已经完成`)
}
async function printAll() {
console.log(`一共${tokens.length}份,正在打印中……`)
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.setExtraHTTPHeaders({'uniedu-sso-token': token})
for(let i = 0; i < tokens.length; i ++){
await printPDF(page, tokens[i], i)
}
await browser.close()
}
printAll()
如果需要自动生成文件夹归类,可以用node的fs.existsSync和fs.mkdirSync方法,先判断有没有这个文件夹,没有则创建
if(!fs.existsSync('dirName')) {
fs.mkdirSync('dirName')
}
5. puppeteer生成截图
这里直接给出最近简单封装的node命令形式的代码作为参考,大部分参数可以参考官方文档
唯一值得说的一个参数是fitContent,这个是我自己加的,可以用于局部的截图,需要html的标签内含有screenshot
这个id,说白了就是需要截图的元素用<div id="screenshot"></div>
包裹起来
const puppeteer = require('puppeteer')
const fs = require('fs')
const args = require('minimist')(process.argv.slice(2))
const clip = {}
args.clipX && (clip.x = Number(args.clipX))
args.clipY && (clip.y = Number(args.clipY))
args.clipW && (clip.width = Number(args.clipW))
args.clipH && (clip.height = Number(args.clipH))
let params = {}
args.imgPath && (params.path = args.imgPath)
args.type && (params.type = args.type)
args.quality && (params.quality = Number(args.quality))
args.fullPage && (params.fullPage = args.fullPage === 'true')
args.omitBackground && (params.omitBackground = args.omitBackground === 'true')
args.encoding && (params.encoding = args.encoding)
Object.keys(clip).length !== 0 && (params.clip = clip)
async function printImg() {
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox'], headless: true})
const page = await browser.newPage()
const htmlContent = fs.readFileSync(args.htmlPath, 'utf-8')
await page.setContent(htmlContent, { waitUntil: 'networkidle0' })
const range = await page.$('#screenshot')
const clip = await range.boundingBox()
const result = args.fitContent === 'true' ? { ...params, clip } : params
await page.screenshot(result)
await browser.close()
}
printImg()
/*
参数说明:
htmlPath: html文件路径
imgPath: 截图保存路径。截图图片类型将从文件扩展名推断出来。如果是相对路径,则从当前路径解析。如果没有指定路径,图片将不会保存到硬盘
type: 指定截图类型, 可以是 jpeg 或者 png。默认 'png'.
quality: 图片质量, 可选值 0-100. png 类型不适用。
fullPage: 如果设置为true,则对完整的页面(需要滚动的部分也包含在内)。默认是false
clipX: 指定裁剪区域相对于左上角(0, 0)的x坐标
clipY: 指定裁剪区域相对于左上角(0, 0)的y坐标
clipW: 指定裁剪区域的宽度
clipH: 指定裁剪区域的高度
omitBackground: 隐藏默认的白色背景,背景透明。默认不透明
encoding: 图像的编码可以是 base64 或 binary。 默认为“二进制”。
fitContent: 设为true,则只对id="screenshot"包裹的内容区域截图
*/
// node 命令示例
// node puppeteer_img.js --htmlPath=./index.html --imgPath=aa.png --fullPage=true --fitContent=true
6. 调用本地chrome
puppeteer默认会安装一个最新版本的chromiue,也可以调起本地的chrome,这时候需要使用puppeteer-core
安装npm i puppeteer-core carlo
const puppeteer = require('puppeteer-core');
//find_chrome模块来源于GoogleChromeLabs的Carlo,可以查看本机安装Chrome目录
const findChrome = require('./node_modules/carlo/lib/find_chrome.js')
;(async () => {
let findChromePath = await findChrome({})
let executablePath = findChromePath.executablePath;
console.log(executablePath)
const browser = await puppeteer.launch({
executablePath,
headless: false
})
const page = await browser.newPage()
await page.goto('https://www.baidu.com/')
// await browser.close()
})()
使用puppeteer生成pdf与截图的更多相关文章
- puppeteer 爬虫 pdf 截图 自动化
puppeteer简介 puppeteer 翻译是操纵木偶的人,利用这个工具,我们能做一个操纵页面的人.puppeteer是一个nodejs的库,支持调用Chrome的API来操纵Web,相比较Sel ...
- wkhtmltopdfhtml php生成pdf快照,网页截图,网页快照完整版 (原)
首先,安装(linux安装为例) 1.下载wkhtmltopdf wget http://download.gna.org/wkhtmltopdf/obsolete/linux/wkhtmltopdf ...
- 生成 PDF 全攻略【1】初体验
经历过多少踩坑,翻看过多少类似博客,下载过多少版本的Jar,才能摸索出正确的代码书写方式,才能实现项目经理需求分析书中的功能点. 本文借一次 JavaEE 生成PDF的颠簸的实现过程,描述中小公司程序 ...
- 【PDF】java使用Itext生成pdf文档--详解
[API接口] 一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/ ...
- Javascript 将 HTML 页面生成 PDF 并下载
最近碰到个需求,需要把当前页面生成 pdf,并下载.弄了几天,自己整理整理,记录下来,我觉得应该会有人需要 :) html2canvas 简介 我们可以直接在浏览器端使用html2canvas,对整个 ...
- js将 HTML 页面生成 PDF 并下载
最近碰到个需求,需要把当前页面生成 pdf,并下载.弄了几天,自己整理整理,记录下来,我觉得应该会有人需要 :) 先来科普两个插件: html2Canvas 简介 我们可以直接在浏览器端使用html2 ...
- 生成pdf phantomjs
注:原创文件,转载请注明出处 使用phantomjs生成还原度比较高的pdf文件,理论上生成word也可以,因需求没有做这块要求,功课留给大家去做了. 下载 https://phantomjs.org ...
- 实践指南-网页生成PDF
一.背景 开发工作中,需要实现网页生成 PDF 的功能,生成的 PDF 需上传至服务端,将 PDF 地址作为参数请求外部接口,这个转换过程及转换后的 PDF 不需要在前端展示给用户. 二.技术选型 该 ...
- 利用Java动态生成 PDF 文档
利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...
随机推荐
- RPA工单查询和下载流程机器人
1.登录业务系统,输入用户名和密码 2.进入下载模块 3.输入下载查询条件 4.进入文件明细单 5.下载文件 视频地址:https://www.bilibili.com/video/BV1964y1D ...
- 修改windows字符集
手动 临时修改cmd默认字符集(代码页) chcp xxxx 自动<打开cmd后应该自动运行dhcp 65001,临时设置为utf-8> D:\Develope\apache-tomcat ...
- 【Java面试】什么是 ISR,为什么需要引入 ISR
Hi,大家好,我是Mic. 一个工作5年的粉丝,在简历上写精通Kafka. 结果在面试的时候直接打脸. 面试官问他:"什么是ISR,为什么需要设计ISR" 然后他一脸懵逼的看着面试 ...
- python采集一下美团外卖数据~~
所需知识点(https://jq.qq.com/?_wv=1027&k=Ap5XvyNN) 1.动态数据抓包演示2.json数据解析3.requests模块的使用4.保存csv 安装命令:re ...
- springboot2+jpa+oracle实例
pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="ht ...
- MIT 6.824 Llab2B Raft之日志复制
书接上文Raft Part A | MIT 6.824 Lab2A Leader Election. 实验准备 实验代码:git://g.csail.mit.edu/6.824-golabs-2021 ...
- Eolink家族成员回归 — 开源服务Eoapi!
Eolink 开源产品又回来了!Eoapi 自 2016 年上架 Github 以来,一直备受国内外开发者的欢迎和好评 ,在2018年 Eolink 为了进一步升级该产品而进行了暂时下架.时隔四年,E ...
- S32K148_CAN驱动(裸机开发)
hello,大家好.今天我又来啦,今天记录一下S32K148-CAN裸机驱动编写,有错误地方欢迎大家指正. CAN的发送接收在S32K148中主要有三种方式,一种是邮箱机制(mailbox),一种FI ...
- 003 Jwt登录流程图
用户\角色\权限 用户是一个基本的单位 用户和角色的关系是多对多,所以要有一张保存用户和角色关系的中间表 角色也不能直接决定这个用户能做什么操作,有哪些权限, 需要再关联权限表决定 角色和权限也是多对 ...
- Winsock Server Code
以下代码来自:https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx #undef UNICOD ...