初探 Headless Chrome
阿新 • • 發佈:2021-10-27
初探 Headless Chrome
xiguaxigua 專心做技術宅什麼是 Headless Chrome
Headless Chrome 是 Chrome 瀏覽器的無介面形態,可以在不開啟瀏覽器的前提下,使用所有 Chrome 支援的特性執行你的程式。相比於現代瀏覽器,Headless Chrome 更加方便測試 web 應用,獲得網站的截圖,做爬蟲抓取資訊等。相比於出道較早的 PhantomJS,SlimerJS 等,Headless Chrome 則更加貼近瀏覽器環境。
如何獲取 Headless Chrome
目前,Mac 上 Chrome 59 beta版本與 Linux 上的 Chrome 57+ 已經開始支援 headless 特性。Windows 上 Chrome 暫時不支援,可以使用Chrome Canary 60進行開發。
如何在終端中使用
在Mac上使用前,建議先繫結 Chrome 的別名
alias google-chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
Linux下無需繫結別名,從官網上下載最新版 Chrome 之後直接執行以下命令即可。然後,在終端中輸入:
google-chrome --headless --disable-gpu --remote-debugging-port=9222 https://github.com
增加 --disable-gpu 主要是為了遮蔽現階段可能觸發的錯誤。此時,Headless Chrome已經成功運行了。開啟瀏覽器,輸入http://localhost:9222,你會看到如下的介面:
在終端中,我們還可以做以下操作:
獲取螢幕截圖:
google-chrome --headless --disable-gpu --screenshot --window-size=1280,1696 https://github.com
獲取頁面為PDF:
google-chrome --headless --disable-gpu --print-to-pdf https://github.com
列印頁面DOM:
google-chrome --headless --disable-gpu --dump-dom https://github.com/
遠端控制
在上文中講述的都使用終端命令啟動 Headless Chrome,下文以獲取截圖為例,嘗試如何在程式裡控制 Headless Chrome。
安裝依賴
npm install lighthouse chrome-remote-interface --save
實現截圖的大體思路為:通過使用 lighthouse 啟動 Headless Chrome,然後通過chrome-remote-interface遠端控制瀏覽器,使用 Page 監控頁面的載入,使用 Emulation 模組調整視口縮放,最終生成一張截圖。
const { ChromeLauncher } = require('lighthouse/lighthouse-cli/chrome-launcher')
const chrome = require('chrome-remote-interface')
const fs = require('fs')
const deviceMetrics = {
width: 1200,
height: 800,
deviceScaleFactor: 0,
mobile: false,
fitWindow: false
}
const screenshotMetrics = {
width: deviceMetrics.width,
height: deviceMetrics.height
}
let protocol
let launcher
function launchChrome () {
const launcher = new ChromeLauncher({
port: 9222,
autoSelectChrome: true,
additionalFlags: ['--window-size=412,732', '--disable-gpu', '--headless']
})
return launcher.run().then(() => launcher)
}
function getScreenShot () {
const { Page, Emulation } = protocol
return Page.enable()
.then(() => {
Emulation.setDeviceMetricsOverride(deviceMetrics) // 配置瀏覽器尺寸
Emulation.setVisibleSize(screenshotMetrics) // 配置截圖尺寸
Page.navigate({ url: 'https://github.com/' })
return new Promise((resolve, reject) => {
Page.loadEventFired(() => {
resolve(Page.captureScreenshot({ format: 'jpeg', fromSurface: true }))
})
})
})
.then(image => {
const buffer = new Buffer(image.data, 'base64')
return new Promise((resolve, reject) => {
fs.writeFile('output.jpeg', buffer, 'base64', err => {
if (err) return reject(err)
resolve()
})
})
})
}
launchChrome()
.then