使用 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。如圖
google-1.png

編輯: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。在下面的字體列表其中添加一句 <dir>/usr/share/fonts/chinese</dir>。如圖:

按 ESC 鍵,輸入 :wq 保存並退出

刷新內容中的字體緩存:fc-cache。到此就完成了

可以通過命令:fc-list 來查看字體列表

使用命令將 HTML 轉 PDF 格式

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

google-4.png

在哪個路徑下運行以上命令,則默認在該路徑下生成個 output.pdf 文件。也可以指定路徑和文件名(不加引號也行),例如:

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

google-5.png


存在的問題及可以嘗試的解決方案

問題:通過以上命令可以將 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。這些這裏就不細究了。


擴展資料


後記

換一種思路,不斷地去尋找新的解決方案,不斷地試錯。

在實踐中成長!

HochenChong

2018-5-17

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章