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

github 地址:	
	https://github.com/GoogleChrome/puppeteer

文档地址:
	https://pptr.dev/

中文文档地址:
	https://zhaoqize.github.io/puppeteer-api-zh_CN/#/

简单说下这个东西是啥:
	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 生成的效果好,有时间这个东西,需好好研究下!

 

你可能感兴趣的:(laravel框架,php,PDF相关技术,javascript)