使用 Chrome Headless 模式将 HTML 转 PDF

使用 Chrome Headless 模式将 HTML 转 PDF

前言

最近遇到了个问题,需要将爬取到的某个网页转成 PDF 格式。在这其中尝试过不少方法,例如使用 IText,wkhtmltopdf 之类的方式。但是由于所获取的 HTML 页面的标签较多,以及有些标签并不完整,或者自闭合标签,样式等问题,从而导致无法成功转换。

也试过使用 HtmlCleaner 这个开源的 Java 语言的 HTML 文档解析器重新生成一个结构较好的 HTML 文档。从代码上来看,格式确实整洁了许多,不过页面的样子稍微变乱了点,而且仍然没有成功转换。

其它的解决思路,例如获取那个网页中的数据,用 Freemarker 重新生成一个符合要求的 HTML 文件啊。不过这样子工作量就比较大了。下次遇到其它 HTML 需要转 PDF 时则需要重新弄一次。不方便重用。

便开始继续换个思路,突然想到,要是能后台直接调用浏览器的打印功能就好了。如此一来,标签等问题就不是什么问题了,浏览器怎么渲染 HTML 页面,打印出来的效果就是如何,也就不用担心样式之类的问题了。

在搜索资料的过程之中,就遇到了本文的主角 —— Chrome 的 Headless 模式下打印 PDF。


Chrome Headless 模式

于我的理解是,无界面(GUI)的运行 Chrome 浏览器。在后台运行,优点在于占用资源少,不用打开图形界面即可,通过命令来操作 Chrome 的功能,例如截图,打印成 PDF 之类的。

理论上安装了 Chrome 浏览器就可以使用该模式。从资料查询来看,Mac 在 Chrome 59 版本及之后,Linux 于 Chrome 57 版本及之后,而 Windows 在 Chrome 60 版本及之后都可以使用该新特性。

不过我这里安装的是当前最新版本:Google Chrome 66.0.3359.181


环境准备及使用

CentOS7 命令界面中安装 Google Chrome 浏览器

配置 yum 下载源:vi /etc/yum.repos.d/google-chrome.repo

在里面添加以下内容:

[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/x86_64
enabled=1
gpgcheck=1
gpgkey=https://dl.google.com/linux/linux_signing_key.pub

安装 Chrome 浏览器:yum -y install google-chrome-stable --nogpgcheck

等待安装成功即可。详情了解可看这篇文章:CentOS7 安装Chrome浏览器

因为 Chrome 不能以 root 用户运行,所以我们还需要修改以下配置文件。先查看以下配置所在位置,通过命令:whereis google-chrome。如图
使用 Chrome Headless 模式将 HTML 转 PDF_第1张图片

编辑:vi /usr/bin/google-chrome,通过 /exec -a 进行搜索,找到以下代码
google-2.png

按 i 键进入编辑模式,在这句话后面追加内容:–no-sandbox –user-data-dir,然后通过命令 :wq 保存退出即可。
google-3.png

CentOS7 安装字体,解决中文乱码问题

在我需要转换为 PDF 的 HTML 之中,使用了黑体和宋体。而在我虚拟机上的的 CentOS7 之中,并没有安装相关的字体,故直接转换的话,会出现乱码问题,所以需要先安装一下字体。具体步骤如下,详情请看此文章(Linux CentOS 7 安装字体库 & 中文字体)

安装字体库:yum -y install fontconfig

创建中文字库的文件夹,依次运行下面的命令:

cd /usr/share/fonts
mkdir chinese

使用 WinSCP 之类的工具将 Windows 字库(C:\Windows\Fonts)下的黑体和宋体上传到刚才创建好的 chinese 目录下

修改 chinese 目录的权限:chmod -R 755 /usr/share/fonts/chinese

安装 ttmkfdir 来搜索目录中的字体信息:yum -y install ttmkfdir

执行 ttmkfdir 命令,汇总生成 fonts.scale 文件:ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir

修改字体配置文件:

vi /etc/fonts/fonts.conf

在 fonts.conf 中的字体列表(Font list),可以在 vi 编辑中使用命令搜索关键字:/Font directory list。在下面的字体列表其中添加一句

/usr/share/fonts/chinese。如图:

按 ESC 键,输入 :wq 保存并退出

刷新内容中的字体缓存:fc-cache。到此就完成了

可以通过命令:fc-list 来查看字体列表

使用命令将 HTML 转 PDF 格式

google-chrome --headless --disable-gpu --print-to-pdf /root/test/test.html

使用 Chrome Headless 模式将 HTML 转 PDF_第2张图片

在哪个路径下运行以上命令,则默认在该路径下生成个 output.pdf 文件。也可以指定路径和文件名(不加引号也行),例如:

google-chrome --headless --disable-gpu --print-to-pdf='/root/test/test.pdf' /root/test/test.html

使用 Chrome Headless 模式将 HTML 转 PDF_第3张图片


存在的问题及可以尝试的解决方案

问题:通过以上命令可以将 HTML 转换为 PDF,不过生成的 PDF 默认是有页眉和页脚的。通过修改 HTML 文件,在其中加入一些 CSS 样式,则生成的 PDF 在最后一页有页脚,其它页面没有。HTML 添加的代码如下:

<style>
@page { 
    margin: 0;
    size: auto;
}
style>

或者

<style>
@media print {
    @page { margin: 0; }
    body { margin: 1.6cm; }
}
style>

思路:Chrome 默认的打印配置是勾选了页眉与页脚的。可以考虑修改默认的配置,不过需要找到配置文件的位置。以图形界面的 Chrome 浏览器为例,在地址栏中输入:chrome://version/ 可以查看到个人资料路径,在该路径下有个 Preferences 文件,上面则记录着一些配置。可以使用文本编辑器打开这个文件,搜索关键词: isHeaderFooterEnabled。该关键词不一定存在,甚至这个配置文件也不一定存在,如果使用默认的配置的话,则没有相关的参数。这时候可以使用 Chrome 打印功能,试着勾选 页眉与页脚,则再次搜索关键词则可以找到。在 Linux 命令行模式下,因为不晓得设置 Chrome 的配置,故也就没有生成相应的文件,从而一直使用的是默认的打印方式,即有页眉与页脚。

可以尝试的方案:可以使用谷歌官方推出的 Headless Chrome 的封装库 Puppeteer 来进行操作,亦或者使用 Selenium 来操作 Headless Chrome。这些这里就不细究了。


扩展资料

  • CentOS7 安装Chrome浏览器

  • Linux CentOS 7 安装字体库 & 中文字体

  • Web自动化之Headless Chrome概览

  • Google 官方说明:Getting Started with Headless Chrome

  • stackoverflow 上的问题:Alter the default header/footer when printing to PDF


后记

换一种思路,不断地去寻找新的解决方案,不断地试错。

在实践中成长!

HochenChong

2018-5-17

你可能感兴趣的:(Linux)