使用node将HTML生成PDF或图片:采用 puppeteer

github 地址:
github.com/GoogleChrom…

文档地址:
pptr.dev/

中文文档地址:
zhaoqize.github.io/puppeteer-a…

简单说下这个东西是啥:
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行 non-headless 模式。
所谓的 headless 就是,以命令行接口的方式,chrome 应该是给我们暴露出了一些接口方法,我们可以通过命令行来控制浏览器的一些操作了。

headless 模式:
	https://developers.google.com/web/updates/2017/04/headless-chrome

我们可以用来做什么:
	1) 生成网页截图或者 PDF 
	2) 高级爬虫,可以爬取大量异步渲染内容的网页 
	3) 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试 
	4) 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题

参考别人的文档,提到了:
	PhantomJS 和 selenium-webdriver

	之前记得想做网页截图,html 生成图片,好像好多教程说的就是这个 PhantomJS,一直没用过。他们应该和 puppeteer 是一类,但是 puppeteer 应该是具有更大的优势,谷歌开发团队维护,而且支持各种 CSS3 和 HTML5 特性吧。
复制代码

好了,不说废话了,大家百度一下,就能搜到大量的 puppeteer 介绍,比我说的都好,开始笔记:

1.安装:
	npm i puppeteer/yarn add puppeteer
		注意:
			安装同时,会根据我们的操作系统,下载最新版本的 Chromium,来确保可以使用这些 API。(下载异常缓慢,可能因为被墙)

			如果想跳过下载 Chromium,可以查看 『环境变量』来设置。(应该是:PUPPETEER_SKIP_CHROMIUM_DOWNLOAD)

	/*
		环境变量:
			Puppeteer 根据某些环境变量来辅助其操作。在安装期间,如果 Puppeteer 没有在环境中找到这些变量,将会从 npm config 文件中,来使用的这些变量(npm 中的配置变量是环境变量的小写形式)。

				HTTP_PROXY, HTTPS_PROXY, NO_PROXY - 定义用于下载和运行 Chromium 的 HTTP 代理设置
				PUPPETEER_SKIP_CHROMIUM_DOWNLOAD - 安装期间,不下载绑定的 Chromium
				PUPPETEER_DOWNLOAD_HOST - 重新指定下载 Chromium 的 URL 地址
				PUPPETEER_CHROMIUM_REVISION - 指定我们想要使用的 Chromium 版本,确保路径有效
				PUPPETEER_EXECUTABLE_PATH - 应该是全局设置 'puppeteer.launch' 的启动路径

			注意:
				PUPPETEER_* 的环境变量,在 puppeteer-core 包中都无效
	 */

2.puppeteer-core
	1.7.0 版本开始,发布一个 puppeteer-core 包,这个包默认不会下载 Chromium

	npm i puppeteer-core/yarn add puppeteer-core

	puppeteer-core 是一个轻量级的 Puppeteer,用于启动现有浏览器安装,或链接一个远程浏览器

	/*
		puppeteer vs puppeteer-core
			puppeteer 是一个浏览器自动化产品。安装时,它会下载一个指定版本的 Chromium,该 Chromium 之后会被 puppeteer-core 来驱动。作为一个用户端产品,puppeteer 提供了一系列的 PUPPETEER_* 环境变量,来调整行为。

			puppeteer-core 是一个类库,用来帮助驱动任何支持 DevTools 协议的软件。puppeteer-core 安装时,不会下载 Chromium。作为一个类库,puppeteer-core 完全通过其编程接口驱动,并忽略所有的 PUPPETEER_* 环境变量。

			总而言之,puppeteer 和 puppeteer-core 的区别是:
				puppeteer-core 安装时,不自动下载 Chromium
				puppeteer-core 忽略所有的 PUPPETEER_* 环境变量

			在大多数的情况下,使用 puppeteer 包就足够了。
			然而,以下情况,我们可以使用 puppeteer-core:
				当我们正在构建 DevTools 协议顶部的另一个用户端产品或类库。例如:可以使用 puppeteer-core 来构建 PDF 生成器,并编写一个自定义的 install.js 脚本来下载 headless_shell,而不用下载 Chromium 以节省磁盘空间。

				你正在捆绑 Puppeteer 以在 Chrome 扩展/浏览器 中使用 DevTools 协议,不需要下载额外的 Chromium 二进制文件

			当使用 puppeteer-core,记得修改 'include' 引入:
				const puppeteer = require('puppeteer-core');
	 */

3.使用
	Puppeteer 至少需要 Node v6.4.0,下面示例中的 async/await,仅在 Node v7.6.0 之后的版本被支持

	Puppeteer 使用起来和其他测试框架类似。创建一个 Br	owser 示例,打开页面,然后使用 Puppeteer API

	示例1 - 跳转到 https://example.com 并保存截图至 example.png
		vim example.js

			const puppeteer = require('puppeteer');

			(async() => {
				const browser = await puppeteer.launch();
				const page = await browser.newPage();	
				await page.goto('http://example.com');
				await page.screenshot({
					path: 'example.png'
				});
				await browser.close();
			})();

		注意:
			Puppeteer 初始化的屏幕大小默认为 800px x 600px。但是这个尺寸可以通过 Page.setViewport() 设置。

		node example.js

	示例2 - 创建一个 PDF
		vim pdf.js

			const puppeteer = require('puppeteer');

			(async() => {
				const browser = await puppeteer.launch();
				const page = await browser.newPage();	
				await page.goto('http://example.com', {
					waitUntil: 'networkidle2'
				});
				await page.pdf({
					path: 'example.pdf',
					format: 'A4',
				});
				await browser.close();
			})();

		node pdf.js

	示例3 - 在页面中执行脚本,获取页面 viewport 的尺寸
		vim get-dimensions.js

			const puppeteer = require('puppeteer');

			(async() => {
				const browser = await puppeteer.launch();
				const page = await browser.newPage();	
				await page.goto('http://example.com');

				const dimensions = await page.evaluate(() => {
					return {
						width: document.documentElement.clientWidth,
						height: document.documentElement.clientHeight,
						deviceScaleFactor: window.devicePixelRatio,
					}
				});

				console.log('Dimensions:', dimensions);

				await browser.close();
			})();

		node get-dimensions.js

4.默认运行时设置
	1>使用 Headless 模式
		Puppeteer 默认以 headless 模式启动 Chromium。为了启动完全版本的 Chromium,当启动浏览器时,设置 'headless' 选项:
			const browser = await puppeteer.launch({
				headless: false, 	// 默认是 true
			}); 

	2>运行一个指定版本的 Chromium
		默认情况下,Puppeteer 下载并使用特定版本的 Chromium 以及其 API 保证开箱即用。 如果要将 Puppeteer 与不同版本的 Chrome 或 Chromium 一起使用,在创建Browser实例时传入 Chromium 可执行文件的路径即可
			const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});

		/*
			Chrome 和 Chromium 的区别:
				官方推荐的文章:
					https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/
				随便搜了个:
					https://www.cnblogs.com/EasonJim/p/8076507.html
		 */

	3>创建一个新的用户配置文件
		Puppeteer 会创建自己的 Chromium 用户配置文件,它会在每次运行时清理。

5.调试建议
	1>关闭 headless 模式 - 有时候查看浏览器展示的内容很有帮助。
		const browser = await puppeteer.launch({headless: false});

	2>执行慢一点 - 通过设置 slowMo 选项,可以让 Puppeteer 操作慢下来,单位为:毫秒。这是帮助我们查看运行时发生了什么的另一种方式。
		const browser = await puppeteer.launch({
			headless: false,
		   	slowMo: 250 // slow down by 250ms
		});

	3>捕获 console 控制台输出 - 可以监听 console 事件。当在 page.evaluate() 调试代码时,这也很方便:
		page.on('console', msg => console.log('PAGE LOG:', msg.text()));
		await page.evaluate(() => console.log(`url is ${location.href}`));

	4>停止测试执行并在浏览器中使用调试器
		1)当启动 Puppeteer 使用 {devtools: true}
			const browser = await puppeteer.launch({devtools: true});

		2)改变默认测试超时时间:
			jest: jest.setTimeout(100000);
			jasmine: jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
			mocha: this.timeout(100000);(别忘记改变测试来使用 function and not '=>')

		3)添加一条包含 'debugger' 的 evaluate 语句,或在一个已存在的语句中添加 debugger
			await page.evaluate(() => {debugger;});

			现在,测试将在上面的evaluate语句中停止执行,并且chrome将在调试模式下停止。

	5.启用详细日志记录 - 通过 puppeteer 命名空间下的 debug 模块,内部的 DevTools 协议流量,将会被记录下来
		# 基本的详细日志记录
		env DEBUG="puppeteer:*" node script.js

		# 通过命名空间可以启用/禁用 debug 输出
		env DEBUG="puppeteer:protocol" node script.js 		// 记录协议 connenct 信息
		env DEBUG="puppeteer:session" node script.js 		// 记录协议 session 信息

		# 协议流量可能相当烦人。该示例会过滤掉所有的网络域名信息
		env DEBUG="puppeteer:session" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'

	6.使用 ndb,轻松调试我们的 Puppeteer(node) 代码
		npm install -g ndb(或者甚至更好,使用 npx)
		在我们的 Puppeteer(node) 代码中,添加 'debugger'
		在运行测试命令前,添加 'ndb'(或 npx ndb),例如:
			ndb jest / ndb mocha(或 npx ndb jest / npx ndb mocha)
复制代码

可算是 看文档+翻译 大体完成,接着,开始安装并测试使用:

1.安装,下载 Chromium 非常慢,可能也下载不下来,应该是被墙了,需要 NPM 配置成国内镜像源。
	https://github.com/GoogleChrome/puppeteer/issues/1597

	淘宝镜像

	好像还有一个软件,可以切换 NPM 镜像源,叫做:
		nrm

	我参考的上面链接,设置的:
		npm config set puppeteer_download_host=https://npm.taobao.org/mirrors

2.只是使用上面最基础的示例,进行测试了下,发现图片和 PDF 的样式,有点问题啊,可能是没有好好熟悉 API,进行配置吧。
	现在的效果,还不如之前的 laravel-snappy 生成的效果好,有时间这个东西,需好好研究下!
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享