Puppeteer 簡介
Puppeteer 是一個node庫,他提供了很多操縱Chrome的API, 讓我們可以通過 javascript
模擬人工操作瀏覽器。既然是瀏覽器,那麼我們在瀏覽器上做的事情, 都可以通過 Puppeteer切換成自動操作;具體 Puppeteer 可以做
- 生成網頁截圖或者 PDF
- 高級爬蟲,可以爬取大量異步渲染內容的網頁
- 模擬鍵盤輸入、表單自動提交、登錄網頁等,實現 UI 自動化測試
- 捕獲站點的時間線,以便追蹤你的網站,幫助分析網站性能問題
運行環境
查看 Puppeteer 的官方 API 你會發現滿屏的 async, await 之類,這些都是 ES7 的規範,所以你需要:
Nodejs 的版本不能低於 v7.6.0, 需要支持 async, await.
需要最新的 chrome driver
chrome driver 在通過 npm 安裝 Puppeteer 的時候會自動跟着下載;
安裝puppeteer
通過 npm 可以直接安裝
npm i puppeteer
基本用法
直接用官網的入門 Demo 演示
const puppeteer = require(' puppeteer');
(async () => {
// 創建一個瀏覽器實例 Browser 對象
const browser= await puppeteer.launch();
// 通過 Browser 對象創建頁面 Page 對象
const page = await browser.newPage();
// page.goto() 跳轉到指定的頁面
await page.goto('https://example.com’);
// 對當前頁面截圖
await page.screenshot({path: 'example.png'});
// 關閉瀏覽器
await browser.close();
})();
創建瀏覽器方法詳解(puppeteer.launch(options))
使用 puppeteer.launch() 運行 puppeteer,它會 return 一個 promise,使用 then 方法獲取 browser 實例, 當然高版本的 的 nodejs 已經支持 await 特性了,所以上面的例子使用 await 關鍵字,這一點需要特殊說明一下,Puppeteer 幾乎所有的操作都是 異步的, 爲了方便代碼維護和閱讀,我們優先使用await 將異步操作轉成同步操作;本文所有 demo 代碼都是用 async, await 方式實現。這個 也是 Puppeteer 官方推薦的寫法。
options 參數詳解
參數名稱 | 參數類型 | 參數說明 |
---|---|---|
ignoreHTTPSErrors | boolean | 在請求的過程中是否忽略 Https 報錯信息,默認爲 false |
headless | boolean | 是否以"無頭"的模式運行 chrome, 也就是不顯示 UI, 默認爲 true |
executablePath | string | 可執行文件的路徑,Puppeteer 默認是使用它自帶的 chrome webdriver, 如果你想指定一個自己的 webdriver 路徑,可以通過這個參數設置 |
slowMo | number | 使 Puppeteer 操作減速,單位是毫秒。如果你想看看 Puppeteer 的整個工作過程,這個參數將非常有用 |
args | Array(String) | 傳遞給 chrome 實例的其他參數,比如你可以使用"--ash-host-window-bounds=1024x768" 來設置瀏覽器窗口大小。更多參數參數列表可以參考這裏 |
handleSIGINT | boolean | 是否允許通過進程信號控制 chrome 進程,也就是說是否可以使用 CTRL+C 關閉並退出瀏覽器 |
timeout | number | 等待 Chrome 實例啓動的最長時間。默認爲30000(30秒)。如果傳入 0 的話則不限制時間 |
dumpio | boolean | 是否將瀏覽器進程 stdout 和 stderr 導入到 process.stdout 和 process.stderr 中。默認爲 false |
userDataDir | string | 設置用戶數據目錄,默認linux 是在 ~/.config 目錄,window 默認在 C:\Users{USER}\AppData\Local\Google\Chrome\User Data, 其中 {USER} 代表當前登錄的用戶名 |
env | Object | 指定對 Chromium 可見的環境變量。默認爲 process.env。 |
devtools | boolean | 是否爲每個選項卡自動打開 DevTools 面板,這個選項只有當 headless 設置爲 false 的時候有效 |
Browser 對象詳解
構建Browser對象有兩個方法:Puppeteer.launch
和 Puppeteer.connect
; Puppeteer.launch
上面案例中有演示,接下來我們看下 Puppeteer.connect
的用法:
const puppeteer = require(' puppeteer');
(async () => {
const browser= await puppeteer.launch();
// 保存瀏覽器的鏈接對象
const browserWSEndpoint = browser.wsEndpoint();
// 手動斷開鏈接
browser.disconnect();
// 重新建立連接,並創建新的 Browser 實例
const browser2 = await puppeteer.connect({browserWSEndpoint});
// 關閉 瀏覽器
await browser2.close();
})();
Browser 對象 API
方法名稱 | 返回值 | 說明 |
---|---|---|
browser.close() | Promise | 關閉瀏覽器 |
browser.disconnect() | void | 斷開瀏覽器連接 |
browser.newPage() | Promise(Page) | 創建一個 Page 實例 |
browser.pages() | Promise(Array(Page)) | 獲取所有打開的 Page 實例 |
browser.targets() | Array(Target) | 獲取所有活動的 targets |
browser.version() | Promise(String) | 獲取瀏覽器的版本 |
browser.wsEndpoint() | String | 返回瀏覽器實例的 socket 連接 URL, 可以通過這個 URL 重新連接 chrome 實例 |
完整的API請插件官網文檔:https://pptr.dev/api/puppeteer.browser
Page 對象Api
Page 提供了與瀏覽器中的單個選項卡或擴展程序後臺頁面進行交互的方法。
一個瀏覽器實例可能有多個頁面實例。也就是多個標籤頁
Page 實例屬性
屬性 | 修飾符 | 類型 | 描述 |
---|---|---|---|
accessibility | readonly | Accessibility | Accessibility 類提供了檢查瀏覽器的可訪問性樹的方法。輔助功能樹由屏幕閱讀器或開關等輔助技術使用。 |
coverage | readonly | Coverage | Coverage 類提供了一些方法來收集有關頁面使用的部分 JavaScript 和 CSS 的信息。 |
keyboard | readonly | Keyboard | Keyboard 提供了一個用於管理虛擬鍵盤的 API。高級 API 是 Keyboard.type(),它接受原始字符並在頁面上生成正確的 keydown、keypress/input 和 keyup 事件。 |
mouse | readonly | Mouse | Mouse 類在主框架 CSS 像素相對於視口左上角操作。 |
touchscreen | readonly | Touchscreen | Touchscreen 類公開觸摸屏事件。 |
tracing | readonly | Tracing | Tracing 類公開跟蹤審覈接口。 |
Page 實例方法
這裏列舉出常用的幾個
方法 | 修飾符 | 描述 |
---|---|---|
$(selector) | 在頁面內部運行 document.querySelector。如果沒有元素與選擇器匹配,則返回值解析爲 null。 | |
$$(selector) | 該方法在頁面內運行 document.querySelectorAll,如果沒有元素與選擇器匹配,則返回值解析爲[]。 | |
$$eval(selector, pageFunction, args) | 該方法在頁面內運行 Array.from(document.querySelectorAll(selector)) 並將結果作爲第一個參數傳遞給 pageFunction。 | |
$eval(selector, pageFunction, args) | 該方法在頁面內運行 document.querySelector,並將結果作爲第一個參數傳遞給 pageFunction。 | |
$x(expression) | 該方法將 XPath 表達式相對於頁面文檔作爲上下文節點進行評估。如果不存在此類元素,則該方法解析爲空數組。 | |
addScriptTag(options) | 向頁面添加具有所需 URL 或內容的 <script> 標記。 | |
addStyleTag(options) | 將帶有所需 URL 的 <link rel="stylesheet"> 標記或帶有內容的 <style type="text/css"> 標記添加到頁面中。這是page.mainFrame().addStyleTag(options) 的快捷方式。 | |
authenticate(credentials) | 爲 HTTP 驗證提供憑據。 | |
bringToFront() | 將頁面置於前臺(激活選項卡)。 | |
browser() | 獲取頁面所屬的瀏覽器。 | |
browserContext() | 獲取頁面所屬的瀏覽器上下文。 | |
click(selector, options) | 該方法使用選擇器獲取元素,如果需要,將其滾動到視圖中心,然後使用 Page.mouse 單擊元素的中心。如果沒有與選擇器匹配的元素,則該方法會拋出錯誤。 | |
close(options) | 關閉頁面。 |
完整的方法查看官網文檔: https://pptr.dev/api/puppeteer.page
Keyboard 對象API
Keyboard提供了一個用於管理虛擬鍵盤的API。高級API是Keyboard.type(),它接受原始字符並在頁面上生成正確的keydown、keypress/input和keyup事件。
使用案例
一個 shift + a的組合按鍵例子
await page.keyboard.down('Shift');
await page.keyboard.press('KeyA');
await page.keyboard.up('Shift');
Keyboard 實例方法
方法 | 修飾符 | 描述 |
---|---|---|
down(key, options) | 觸發一個 keydown 事件。 | |
press(key, options) | 快捷方式,等同於 Keyboard.down() 和 Keyboard.up()。 | |
sendCharacter(char) | 觸發一個 keypress 和 input 事件。這不會觸發 keydown 或 keyup 事件。 | |
type(text, options) | 對文本中的每個字符發送一個 keydown、keypress/input 和 keyup 事件。 | |
up(key) | 觸發一個 keyup 事件。 |
Mouse 對象 API
Mouse類在相對於視口左上角的主框架CSS像素中操作。
每個page對象都有自己的Mouse,可以通過[page.mouse]訪問。
Mouse 使用案例
await page.mouse.move(0, 0);
await page.mouse.down();
await page.mouse.move(0, 100);
await page.mouse.move(100, 100);
await page.mouse.move(100, 0);
await page.mouse.move(0, 0);
await page.mouse.up();
Mouse 實例方法
方法 | 修飾符 | 描述 |
---|---|---|
click(x, y, options) | 鼠標單擊事件的快捷方式,相當於 mouse.move、mouse.down 和 mouse.up。 | |
down(options) | 模擬鼠標按下事件。 | |
drag(start, target) | 發送一個拖動事件。 | |
dragAndDrop(start, target, options) | 依次執行拖動、拖入、懸停和放置操作。 | |
dragEnter(target, data) | 發送一個拖入事件。 | |
dragOver(target, data) | 發送一個懸停事件。 | |
drop(target, data) | 依次執行拖入、懸停和放置操作。 | |
move(x, y, options) | 將鼠標移動到指定座標。 | |
reset() | 將鼠標重置爲默認狀態:沒有按下任何按鈕;位置在 (0,0)。 | |
up(options) | 釋放鼠標按鈕。 | |
wheel(options) | 發送一個鼠標滾輪事件。 |
JSHandle 對象
表示對JavaScript對象的引用。可以使用 Page.evaluateHandle()
創建隊列。
句柄防止引用的JavaScript對象被垃圾收集,除非句柄被故意釋放。JSHandle在其關聯的框架被導航離開或父上下文被破壞時自動釋放。
句柄可以用作任何求值函數(如Page.$)的參數eval()、Page.evaluate()和Page.evaluateHandle()。它們被解析爲其引用的對象。
方法 | 修飾符 | 描述 |
---|---|---|
asElement() | 如果句柄是 ElementHandle 的實例,則返回該句柄本身,否則返回 null。 | |
dispose() | 釋放句柄引用的對象,以便進行垃圾回收。 | |
evaluate(pageFunction, args) | 使用當前句柄作爲其第一個參數,評估給定函數。 | |
evaluateHandle(pageFunction, args) | 使用當前句柄作爲其第一個參數,評估給定函數。 | |
getProperties() | 獲取表示當前句柄屬性的句柄映射。 | |
getProperty(propertyName) | 從引用對象中獲取單個屬性。 | |
jsonValue() | 表示引用對象可序列化部分的普通對象。 | |
remoteObject() | 提供對支持此句柄的 Protocol.Runtime.RemoteObject 的訪問。 | |
toString() | 返回 JSHandle 的字符串表示形式。 |
ElementHandle 對象
ElementHandle表示頁面的DOM元素。
如果要點擊某個Dom元素,必須將對象轉換成 ElementHandle 類型。只有 ElementHandle 類型纔有 點擊方法
JSHandle 轉 ElementHandle 類型使用: asElement() 方法
方法 | 修飾符 | 描述 |
---|---|---|
$(selector) | 在當前元素中查找與給定選擇器匹配的元素。 | |
$$(selector) | 爲所有匹配給定選擇器的元素返回當前元素。 | |
$$eval(selector,pageFunction,args) | 在當前元素中與給定選擇器匹配的元素數組上執行給定函數。如果給定的函數返回一個promise,那麼這個方法將等待promise解析。 | |
click(this,options) | 如果需要,此方法將元素滾動到視圖中,然後使用Page.mouse單擊元素的中心。如果元素從DOM分離,則該方法拋出錯誤。 |
更多內容請查看官方文檔: https://pptr.dev/api/puppeteer.elementhandle
後記
官網文檔非常詳細,強烈建議將文檔閱讀一遍再上手;
文檔地址: https://pptr.dev/