使用Selenium將網頁列印成PDF

Terrence
Jan 20, 2021

--

在爬某些資料的時候,我有時需要將網頁內容一併保留,以供未來回頭檢查資料正確性。

將網頁列印成PDF保存,主要有3個步驟:

  1. 打開要列印的網頁
  2. 執行「列印」並選擇「另存為PDF」
  3. 保存PDF

看上去很簡單對吧,但其中涉及的問題有好幾個,其中最核心的問題就是如何控制瀏覽器的列印選項(選擇另存為PDF)。

原先我打算使用Selenium執行列印的JavaScript,再控制Selenium點選選項,結果在執行JavaScript時出現timeout錯誤,上Stack Overflow看看發現這篇,終於解決我的問題,下面就來說說我是怎麼解決的。

from selenium import webdriver
import json

# 輸入PDF保存的路徑
PDF_savepath = r'E:\Document'

chrome_options = webdriver.ChromeOptions()
appState = {
'recentDestinations': [
{
'id': 'Save as PDF',
'origin': 'local',
'account': ''
}
],
'selectedDestinationId': 'Save as PDF',
'version': 2
}
prefs = {
'printing.print_preview_sticky_settings.appState': json.dumps(appState),
'savefile.default_directory': PDF_savepath
}
chrome_options.add_experimental_option('prefs', prefs)

chrome_options.add_argument('--kiosk-printing')

# 輸入chromedriver的路徑
driver = webdriver.Chrome(
r'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe', options=chrome_options)
driver.implicitly_wait(10)

driver.get('https://www.cpc.com.tw/cp.aspx?n=47')
driver.execute_script('window.print();')

driver.close()

如何控制瀏覽器的列印選項

我使用Chrome作為瀏覽器,來抓中油的液化石油氣牌價表,可以看到在這個網頁中有一個「友善列印」的按鈕,這個按鈕對應了window.print();的JavaScript,相當於右鍵-列印的功能,因此如果可以藉由Selenium直接來執行這個JavaScript,就等於可以使用列印了。

在執行window.print();後,瀏覽器會彈出一個列印選項的頁面,這裡才是主要的問題點。必須將「印表機」那個選項選為「另存為PDF」,接著按下「儲存」,這要怎麼做到呢?

這裡的思路是透過調整Chrome的預設選項,把列印選項設定成「另存為PDF」,也就是appState那個dictionary在做的事情,接著用json.dump()的方法將appState丟到prefs中,再將prefs寫入到Chrome的Preferences檔案(Chrome的預設選項檔案)即可。

Preferences檔案路徑

Windows:%LOCALAPPDATA%\Google\Chrome\User Data\Default

MacOS:~/Library/Application Support/Google/Chrome

然後就是來處理按「儲存」按鈕的事情了,透過將Chrome的模式設定為--kiosk-printing,就可以在預設的列印選項下直接儲存或列印。

這個--kiosk-printing是什麼呢?根據網路上的資料,這可以將Chrome設定為POS機(收銀機系統)的模式,這種模式的作用是在背景中進行列印,不需要另外點選按鈕或是輸入設定(會依預設選項來列印),這樣就解決了按「儲存」按鈕的事情。不得不說,我自己真是想破頭也想不到用這種方式處理,Amazing!

設定保存PDF的路徑

現在我成功把PDF抓下來了,但它被保存到預設的「下載」檔案夾中,我們可以自己決定要保存到哪個檔案夾嗎?

當然可以,參考Stack Overflow的這篇,保存PDF的預設路徑是透過savefile.default_directory這項參數來設定的,因此我們只需要修改這項參數,並將其寫入到Chrome的預設選項中。需要注意的是,有另一個叫做download.default_directory的參數,雖然與我們要修改的參數很像,但作用完全不一樣,記得不要改錯咯。

參考資料

  1. https://stackoverflow.com/questions/59893671/pdf-printing-from-selenium-with-chromedriver
  2. https://stackoverflow.com/questions/54578876/selenium-chrome-save-as-pdf-change-download-folder

--

--

Terrence
0 Followers

非專業工程師,沒事喜歡寫程式,也順便記錄一些實作心得