Chrome 59 在 2017 年推出無頭模式,讓您能在無人看管的環境中執行瀏覽器,而不會看到任何可見的 UI。也就是說,即使沒有 Chrome,也可以執行 Chrome。
透過 Puppeteer 或 ChromeDriver 等專案,無頭模式是瀏覽器自動化的熱門選擇。以下是使用無頭模式的基本指令列範例,為指定網址建立 PDF 檔案:
chrome --headless --print-to-pdf https://developer.chrome.com/
無頭介面的運作方式
在探討 Headless 的運作方式之前,建議您先瞭解「舊的」頭戴式運作方式。先前的指令列程式碼片段使用 --headless
指令列旗標,表明 Headless 只是一般 Chrome 瀏覽器的運作模式。但出乎意料,這並不正確。
事實上,舊的 Headless 是獨立的替代瀏覽器實作項目,原本是同一個 Chrome 二進位檔的一部分。也不會分享 //chrome
中的任何 Chrome 瀏覽器程式碼。
實作及維護獨立的 Headless 瀏覽器會帶來大量工程負擔。此外,Headless 是一項獨立的實作,因此有專屬的錯誤和功能,無法在頭版 Chrome 中呈現。這會造成自動化瀏覽器測試出現混淆,這類測試可能會在無頭模式下傳入,但在無頭模式下失敗,甚至反過來。
此外,「無頭」也排除了任何仰賴瀏覽器擴���功能安裝的自動化測試。其他瀏覽器層級函式也是如此;除非 Headless 另外有獨立的實作,否則不受支援。
Chrome 團隊現已整合無頭和頭版模式。
新的無頭模式自 Chrome 112 起推出。在這個模式下,Chrome 會建立 但不會顯示任何平台視窗所有其他函式 (現有和未來) 均可使用,沒有限制。
使用無頭模式
如要使用新的無頭模式,請傳遞 --headless=new
指令列標記:
chrome --headless=new
目前,下列使用者仍可使用舊的無頭模式:
chrome --headless=old
在 Puppeteer 中
如何在 Puppeteer 中啟用新的無頭模式:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: 'new',
// `headless: true` (default) enables old Headless;
// `headless: 'new'` enables new Headless;
// `headless: false` enables "headful" mode.
});
const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');
// …
await browser.close();
Selenium-WebDriver 中
如何在 Selenium-WebDriver 中使用新的無頭模式:
const driver = await env
.builder()
.setChromeOptions(options.addArguments('--headless=new'))
.build();
await driver.get('https://developer.chrome.com/');
// …
await driver.quit();
如需詳細資訊,包括使用其他語言繫結的範例,請參閱參議院團隊的網誌文章。
指令列旗標
全新「無頭」模式提供下列指令列旗標。
--dump-dom
--dump-dom
旗標會將目標頁面的序列化 DOM 列印為 stdout。例如:
chrome --headless=new --dump-dom https://developer.chrome.com/
這與列印 HTML 原始碼不同,這項作業只需使用 curl
即可。為了提供 --dump-dom
的輸出內容,Chrome 會先將 HTML 程式碼剖析為 DOM,執行任何可能會改變 DOM 的 <script>
,再將該 DOM 改回 HTML 的序列化字串。
--screenshot
--screenshot
旗標會擷取目標頁面的螢幕截圖,並將其儲存為目前工作目錄中的 screenshot.png
。這在與 --window-size
旗標合併時特別實用。
例如:
chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/
--print-to-pdf
--print-to-pdf
標記會將目標頁面以名為 output.pdf
的 PDF 格式儲存在目前的工作目錄中。例如:
chrome --headless=new --print-to-pdf https://developer.chrome.com/
您可以選擇新增 --no-pdf-header-footer
標記,藉此省略列印標頭 (包含目前的日期和時間) 和頁尾 (包含網址和頁碼)。
chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/
不支援:--no-pdf-header-footer
標記後方的功能先前搭配 --print-to-pdf-no-header
標記提供。如果使用舊版,您可能需要改回使用舊的標記名稱。
--timeout
--timeout
標記定義了最長等待時間 (以毫秒為單位),即使頁面仍在載入中,--dump-dom
、--screenshot
和 --print-to-pdf
仍會擷取網頁內容。
chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/
--timeout=5000
標記會指示 Chrome 最多等待 5 秒後才能列印 PDF。因此,這項程序最多需要 5 秒才能執行。
--virtual-time-budget
--virtual-time-budget
可做為任何時間相依程式碼 (例如 setTimeout
/setInterval
) 的「快轉」。它會強制瀏覽器盡快執行網頁的任何程式碼,同時讓網頁相信網頁會花費時間。
為了說明其用途,請考慮使用此示範,此示範使用 setTimeout(fn, 1000)
每秒增加、記錄及顯示計數器。以下是相關程式碼:
<output>0</output>
<script>
const element = document.querySelector('output');
let counter = 0;
setInterval(() => {
counter++;
console.log(counter);
element.textContent = counter;
}, 1_000);
</script>
一秒後,該頁面會包含「1」、2 秒後「2」等。 如果要在 42 秒後擷取網頁狀態並儲存為 PDF 檔,方法如下:
chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time
--allow-chrome-scheme-url
如要存取 chrome://
網址,必須使用 --allow-chrome-scheme-url
旗標。
自 Chrome 123 版起,您可以使用這個標記。範例如下:
chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu
偵錯
由於 Chrome 在無頭模式下會確實隱藏,因此解決問題可能並不容易。您可以透過與有頭 Chrome 類似的方式,對 Headless Chrome 偵錯。
使用 --remote-debugging-port
指令列旗標,以無頭模式啟動 Chrome。
chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/
這會將專屬的 WebSocket 網址輸出至 stdout,例如:
DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9
在有頭 Chrome 執行個體中,我們可以使用 Chrome 開發人員工具遠端偵錯功能連線至無頭目標並進行檢查。
- 前往
chrome://inspect
,然後點選「Configure...」按鈕。 - 輸入 WebSocket 網址中的 IP 位址和通訊埠號碼。
- 在上一個範例中,我輸入了
127.0.0.1:60926
,
- 在上一個範例中,我輸入了
- 按一下 [完成]。您應該會看見一個遠端目標,其中列出了其所有分頁和其他目標。
- 按一下「檢查」即可存取 Chrome 開發人員工具,並檢查遠端無頭目標,包括網頁的即時檢視畫面。
意見回饋:
我們希望能聽聽您對新的無頭模式的意見。如果遇到任何問題,請回報錯誤。