基于Node+HeadlessBrowser的瀏覽器自動化方案
什么是無頭瀏覽器(Headless Browser)?
無頭瀏覽器,就像是一個沒有用戶界面的瀏覽器程序。你可以想象它就是一個“隱形”的瀏覽器,只不過它沒有圖形界面,但能做我們用普通瀏覽器所能做的大部分事情,比如打開網頁、執行 JavaScript、進行頁面互動等。無頭瀏覽器最常用的場景就是在自動化測試、網頁抓取、服務器上執行任務等不需要用戶界面的場合。
使用無頭瀏覽器,你無需打開真正的瀏覽器窗口就可以讓程序去瀏覽網頁、錄制操作、生成截圖等等,特別適合那些需要在沒有人手動操作的情況下處理網頁內容的任務。
特性 | Playwright | Puppeteer | Selenium | PhantomJS |
---|---|---|---|---|
支持瀏覽器 | Chromium, Firefox, WebKit | Chromium | 所有主流瀏覽器 | 已內置 WebKit |
平臺支持 | Windows, Mac, Linux | Windows, Mac, Linux | Windows, Mac, Linux | Windows, Mac, Linux |
多瀏覽器支持 | 是 | 否 | 是 | 否 |
API 現代性 | 現代且易用 | 現代且易用 | 較復雜,學習曲線陡峭 | 較簡單 |
開發活躍度 | 活躍且增長快 | 活躍 | 非常活躍 | 已停止維護 |
適用場景 | 自動化測試、爬蟲、跨瀏覽器兼容性測試 | 瀏覽器自動化測試和爬蟲 | 復雜測試流程 | 靜態網頁抓取 |
啟動速度 | 快 | 快 | 較慢 | 快 |
資源占用 | 中 | 中 | 高 | 低 |
文檔和社區支持 | 良好 | 優秀 | 廣泛 | 限制, 文檔停滯 |
- Playwright:適合需要多瀏覽器支持的項目,API 現代且跨平臺,對新功能的支持很快。
- Puppeteer:專注于 Chromium,適合簡單的自動化測試和爬蟲任務。
- Selenium:對于復雜的跨瀏覽器測試任務是很好的選擇,但需要較多的配置和學習。
- PhantomJS:雖然輕量且快速,但由于停止維護,而其使用逐漸減少,不建議用于新項目。
一、依賴安裝
以下用Playwright
為例,實現幾個模擬瀏覽器操作的案例
// 安裝無頭瀏覽器依賴
npm i playwright --save
// 安裝瀏覽器內核
npx playwright install
二、具體自動化操作
ScreenHotUtils.js提供了三個案例方法
- 對目標網頁進行截取
- 獲取目標頁面的大標題
- 獲取目標頁面Window對象的任意屬性
// 注入chromium內核
const { chromium } = require('playwright');/*** 異步暫停方法* @param {number} delay - 時長(以毫秒為單位)* @returns {Promise<void>}*/
const sleep = delay => new Promise(resolve => setTimeout(resolve, delay));/*** 網頁截屏方法* @param {string} webPageUrl - 目標網頁地址* @param {number} loadDelay - 網頁加載延時(以毫秒為單位)* @param {number} width - 瀏覽器寬度* @param {number} height - 瀏覽器高度* @param {boolean} fullPage - 是否進行全屏長截圖* @returns {Promise<Buffer>} - 截圖圖像的Buffer*/
const captureWebPageScreenshot = async (webPageUrl,loadDelay = 1000,width = 1980,height = 1024,fullPage = false
) => {// 創建瀏覽器對象const browser = await chromium.launch();// 創建一個新的頁面const page = await browser.newPage({viewport: {width,height,},});// 跳轉到目標頁await page.goto(webPageUrl);// 等待頁面加載完成await page.waitForLoadState('load');// 頁面加載延時await sleep(loadDelay);// 截圖,并獲取一個Bufferconst screenFileBuffer = await page.screenshot({ fullPage });// 關閉瀏覽器await browser.close();return screenFileBuffer;
};/*** 獲取網頁標題* @param {string} webPageUrl - 目標網頁地址* @param {number} loadDelay - 網頁加載延時(以毫秒為單位)* @returns {Promise<string>} - 網頁標題*/
const getWebPageTitle = async (webPageUrl, loadDelay = 1000) => {// 創建瀏覽器對象const browser = await chromium.launch();const page = await browser.newPage();await page.goto(webPageUrl);await page.waitForLoadState('load');await sleep(loadDelay);// 獲取頁面標題const title = await page.title();await browser.close();return title;
};/*** 獲取Window屬性* @param {string} webPageUrl - 目標網頁地址* @param {string[]} propertyNames - 要獲取的屬性名稱列表* @returns {Promise<string>} - 獲取的屬性值*/
const getWindowProperty = async (webPageUrl, propertyNames) => {const browser = await chromium.launch();const page = await browser.newPage();await page.goto(webPageUrl);await page.waitForLoadState('load');// 使用 evaluate 在頁面上下文中運行腳本const propertyValue = await page.evaluate(propertyNames => {const result = propertyNames.reduce((pre, prop) => {pre = pre[prop];return pre;}, window);return result;}, propertyNames);await browser.close();return propertyValue;
};module.exports = {getWebPageTitle,getWindowProperty,captureWebPageScreenshot,
};
三、執行測試
const {getWebPageTitle,captureWebPageScreenshot,getWindowProperty,
} = require('./ScreenHotUtils');
const fs = require('fs');
const path = require('path');(async () => {const webPageUrl = `http://www.baidu.com`;// 執行截圖動作const fileBuffer = await captureWebPageScreenshot(webPageUrl);// 寫入本地 | 上傳OSS | 其他fs.writeFileSync(path.resolve(__dirname, './screenShot.png'), fileBuffer);// 獲取頁面標題const pageTitle = await getWebPageTitle(webPageUrl);console.log('PageTitle', pageTitle); // 百度一下 你就知道// 獲取頁面cookieconst cookie = await getWindowProperty(webPageUrl, ['document', 'cookie']);console.log('Cookie:', cookie); // cookie......
})();
效果:
就這樣,我們可以輕松獲得一個頁面截圖,通過代碼就能在不打開瀏覽器的情況下獲取到網頁的圖像,來實現一些自動化巡檢&截圖工具。