前端爬蟲 Puppeteer 介紹
前言
最近在研究前端爬蟲,剛好看到 Puppeteer,就想著分享給大家,於是有了這篇。
爬蟲(web crawler/web scraping)
爬蟲主要的目標是自動地做些什麼事情,包含資料搜集、測試、執行任務…等等,藉此提高工作效率。
網路爬蟲的主要優勢和需求主要體現在以下幾個方面:
- 自動化測試 (automated testing)
- 模擬使用者操作、提交表單等
- 可以為應用程式開發、軟體測試和網站管理等提供重要的支援
- 減少人力成本,建立工作模式 (SOP)。
- 資料收集 (data collecting)
- 縮短了手動收集和處理資訊的時間,提升了工作效率
- 可以對資訊進行解析,並且有結構性的儲存,便於後續的使用或分析
- 自動化執行任務 (automated tasks)
- 包含以上內容。
在使用過程中也需要注意尊重網站擁有者的權益,遵守機器人排除協定(Robots Exclusion Protocol)和各種相關法規,避免對被爬取的網站造成不必要的負擔或侵犯。
爬蟲套件的比較差異
常見的網頁爬蟲套件這三個套件(Puppeteer、Cheerio 和 Selenium)在前端爬蟲中扮演不同的角色,各自有其優缺點和特點。
Puppeteer
- 優點:
- 提供了完整的瀏覽器控制能力,可模擬使用者的操作瀏覽器行為,支援 JavaScript、HTML、CSS 的渲染和交互。
- 可以用來進行網頁自動化能力,包括頁面導航、表單填寫、截圖、PDF 生成等工作。
- 具有豐富的 API 可以直接操作網頁上的元素和事件。
- Puppeteer 是一個由 Google 開發的 Node.js 庫,專門用於Chrome 瀏覽器的控制和操作。
- Puppeteer 使用真實的瀏覽器進行操作,因此能夠處理 JavaScript 渲染的頁面,適用於單頁應用程序(SPA)和動態網站的爬取。
- 可以模擬用戶交互,使其在網站上執行各種操作,如點擊、滾動等。
- 缺點:
- 需要較多的系統資源,因為它啟動了一個完整的瀏覽器進程用於模擬了完整的瀏覽器,。
- 相對於其他輕量級的爬蟲工具,Puppeteer 比較慢且耗時。
- 如果只是需要解析靜態網頁內容,可能顯得過於龐大。
- 需要更多的學習成本,因為它使用了一套複雜的 API。
Cheerio
- 優點:
- 非常輕量級,適用於解析靜態 HTML 內容。
- 語法簡單易懂,使用 jQuery 風格的 API,方便選擇、操作和提取 DOM 元素。
- 適合處理大量數據,效率較高。
- Cheerio 是一個基於 Node.js 的 HTML 解析庫,用於解析和操作 HTML 文檔。它非常適靜態網頁的爬取,尤其是當你只需要從頁面中提取數據而不需要進行交互時。
- 輕量級且簡單易用,適合快速開發小型爬蟲。
- 缺點:
- Cheerio 只能處理靜態內容,無法執行 JavaScript,因此無法處理需要 JavaScript 動態生成的內容。
- 不支援瀏覽器渲染,無法模擬瀏覽器行為。
- Cheerio 無法處理 JavaScript 渲染的頁面,因此對於 SPA 和動態網站可能不太適用。
- 不能模擬用戶交互,無法執行類似點擊和提交表單的操作。
Selenium
- 優點:
- 跨平台性強,支援多種瀏覽器(Chrome、Firefox 等)。
- 可以模擬人工操作,支援 JavaScript 执行。
- 可以用多種語言進行控制,如 Python、Java、JavaScript 等。
- Selenium 是一個跨瀏覽器的自動化測試工具,可以模擬用戶在瀏覽器中的操作。它支持多種編程語言,並且可以用於爬取需要用戶交互的網站。
- 能夠處理 JavaScript 渲染的頁面,適用於 SPA 和動態網站。
- 缺點:
- 相較於 Puppeteer,Selenium 在性能和速度上可能稍微較慢。
- 安裝和配置有一定複雜度,需要下載驅動器以及設定環境變數等。
- Selenium 需要下載和配置瀏覽器驅動程序,而且通常比其他兩種庫更慢,因為它模擬了真實的瀏覽器行為。
- 對於簡單的靜態網頁爬取任務,Selenium 可能會顯得過於複雜。
總結:
- 如果你需要模擬完整的瀏覽器行為且操作較多互動性的內容,Puppeteer 和 Selenium 可能更適合你。
- 如果你只需要簡單地解析靜態 HTML 頁面,Cheerio 是一個輕量級的選擇。
- 每個套件都有其獨特的優勢和限制,根據你的具體需求選擇合適的工具。
Puppeteer 介紹
Puppeteer 是由 Google 開發的 Node.js 函式庫,提供方便的 API 來進行網頁測試、屏幕截圖和網頁爬蟲等應用,但僅限於使用 Chromium 瀏覽器引擎的瀏覽器,例如:Google Chrome 或 Microsoft Edge。
- Chromium 瀏覽器 !== Chrome 瀏覽器
- Chromium是一個由 Google 主導的開源瀏覽器項目,它提供了一個開放的、可自由使用的瀏覽器引擎,供開發人員使用。
- Chromium 雖然和 Chrome 九成像,但它其實是 Chrome, Edge 的基礎版本。
- Chromium 提供了 Chrome 的基本架構和核心功能,而 Chrome 在這個基礎上增加功能,成為一個提供給使用者的完整產品。
- Chromium 就像是汽車引擎,而 Chrome 就像是整台汽車
- Puppeteer 的許多用途包括:
- 產生頁面的截圖和 PDF
- 爬取 SPA(單一頁面應用程式)並產生預渲染內容(即 "SSR"(伺服器端渲染))
- UI 自動化測試,模擬表單提交,鍵盤輸入,點擊等行為
- 建立一個最新的自動化測試環境。
- 使用最新的 JavaScript 和最新的 Chrome 瀏覽器執行測試案例
- 捕獲網站的 timeline trace(時間軸跟踪),用來幫助分析效能問題
- 測試 Chrome 擴充功能
Puppeteer 預設是以 headless(無頭)模式運行。headless 模式是指在爬蟲過程中不顯示瀏覽器視窗畫面,雖然看不到畫面但仍然會執行畫面的渲染過程,也就是說 HTML 的解析、CSS 的套用和 JavaScript 都會正常執行,這樣才能確保畫面內容是正確且完整的。
因為無頭模式少了顯示結果的處理不會做屏幕繪製,所以相較於有頭模式,更能節省資源;但是在開發上有頭模式會方便許多,因為瀏覽器會將渲染好的頁面展示出來,包含了:
- 處理用戶的交互
- 應用動畫效果
- 重新繪製頁面元素
- 任何有關圖像輸出至瀏覽器的過程…等
無論在無頭模式或有頭模式下,一定要做關閉瀏覽器的動作,無頭模式雖然看不到瀏覽器畫面,實際上背景仍然會有一個瀏覽器真的在跑。所以如果爬蟲完沒有確實地關閉瀏覽器,那麼整個程式就仍然還在運行中,需要手動 Ctrl + C 停止執行。在寫腳本的時候,一定要記得在結束或是發生錯誤的地方把瀏覽器關閉,才能好好地釋放資源。
如果希望變更為一般模式,可以藉由設定選項變更為有頭模式,如下:
// 一般模式(有頭模式)
const browser = await puppeteer.launch({
headless: false,
});
// 無頭模式(Puputeer 預設模式)
const browser = await puppeteer.launch({
headless: 'new',
});
// 關閉瀏覽器
browser.Close()
Puppeteer 安裝
Puppeteer 會下载最新版本的Chromium(~170MB Mac,~282MB Linux,~280MB Win),以保證可以使用 API。
# 使用 npm
npm i puppeteer
# 使用 yarn
yarn add puppeteer
# 使用npm
npm i puppeteer-core
# 使用yarn
yarn add puppeteer-core
自 1.7.0 版本以来,官方維護團隊都會發布一個 puppeteer-core 函式庫,是一個的輕量級的 Puppeteer 版本,用於啟動現有瀏覽器安裝或連接到遠程安裝。
Puppeteer 程式碼語法
起手式
const puppeteer = require("puppeteer");
(async () => {
// 啟動瀏覽器並開啟一個新的空白頁面
const browser = await puppeteer.launch();
const page = await browser.newPage();
// 將頁面導航至 URL
await page.goto("https://developer.chrome.com/");
// 關閉
await page.close();
await browser.close();
})();
常用語法
const puppeteer = require("puppeteer");
(async () => {
// 啟動瀏覽器並開啟一個新的空白頁面
const browser = await puppeteer.launch({
headless: false,
defaultViewport: { width: 1400, height: 900 },
});
const page = await browser.newPage();
// 前往指定 URL
await page.goto("https://developer.chrome.com/");
// 設定瀏覽器尺寸
await page.setViewport({ width: 1080, height: 1024 });
// 在欄位,輸入文字 "js-text"
await page.type(".devsite-search-field", "js-text");
// 操控鍵盤 "Enter"
await page.keyboard.press("Enter");
// 等待元素,出現在頁面中
const searchResultSelector = "a.gs-title";
await page.waitForSelector(searchResultSelector);
// 點擊元素
await page.click(searchResultSelector);
const textSelector = await page.waitForSelector(".devsite-page-title");
// 在瀏覽器執行 JavaScript,取得元素資訊
const fullTitle = await textSelector?.evaluate((el) => el.textContent);
// 取得頁面尺寸資訊
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio,
};
});
// 列印結果
console.log('The title of this blog post is "%s".', fullTitle);
console.log("Dimensions:", dimensions);
// 畫面截圖
await page.screenshot({ path: "example.png" });
await page.goBack(); // 回到上一頁
await page.goForward(); // 前往下一頁
await page.reload(); // 重新整理
await page.close();
await browser.close();
})();
參考文獻
- Puppeteer 官方文件
- 初識Puppeteer - 手把手教學
- Wait For Page to Load in Puppeteer: 4 Methods Compared
- Cheerio vs Puppeteer
- Puppeteer vs Selenium
- ChatGPT