laravel框架|使用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 包,这个包默认不会下载 Chromiumnpm i puppeteer-core/yarn add puppeteer-corepuppeteer-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.jsconst 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.jsconst 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.jsconst 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框架|使用node将HTML生成PDF或图片(采用 puppeteer)】

    推荐阅读