puppeteer puppeteer 是一個通過DevTools 協議提供高級API 來控制 chrome,chromium 的 NODE庫; puppeteer預設運行在 headless 模式, 也可配置後運行在全模式(non headless). puppeteer可以做什麼 大部分在瀏覽器 ...
puppeteer
puppeteer 是一個通過DevTools 協議提供高級API 來控制 chrome,chromium 的 NODE庫; puppeteer預設運行在 headless 模式, 也可配置後運行在全模式(non-headless).
puppeteer可以做什麼
大部分在瀏覽器里手動執行的動作都可以通過puppeteer實現! 這裡有幾個列子來讓你開始.
- 生成頁面截圖和PDF.
- 爬取單頁面應用生成提前渲染的內容(例如 SSR).
- 自動提交表單, UI測試, 鍵盤輸入等.
- 創建最新的自動化的測試環境,在最新的 chrome 里使用 js 和瀏覽器的最新特性來運行你的測試.
- 捕獲網站的跟蹤時間線以幫助診斷性能問題.
開始
安裝
為了在你的項目里使用puppeteer, 執行:
npm i puppeteer
# 或者 yarn add puppeteer
提示: 安裝puppeteer是,會下載最新版本的chromium(Mac下170 M, Windows下282M))以保證API正常工作. 要跳過這一步,請參閱環境變數().
例子
提示: puppeteer需要 Node V6.4.0及以上版本, 但以下例子中使用了在Node V7.60及以上版本中的 async/await .
使用過其它瀏覽器測試框架的人對puppeteer也會熟悉. 創建Browser實列, 打開頁面,然後使用puppeteer API操作頁面.
Example - 導航到 https://example.com 截圖後保存為example.png.
保存如下文件為 example.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
執行下麵命令 node example.js
puppeteer 設置出時頁面尺寸為 800 x 600px ,截圖尺寸也是這個. 通過Page.setViewport() 設置個性化頁面尺寸.
Example - 創建PDF
文件保存為hn.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
await page.pdf({path: 'hn.pdf', format: 'A4}');
await browser.close();
})();
執行如下命令 node hn.js
, 查看 Page.pdf() API 尋找更多關於創建PDF的信息.
Example - 在頁面上下文中執行js
保存為 get-dimensions.js
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio
}
})
})()
執行如下命令 node get-dimensions.js
, 查看Page.evaluate() API 獲取關於evaluate和相關方法 (如:evaluateOnNewDocument, exposeFunction)的詳細信息.
運行時的預設設置
- 使用無頭瀏覽器模式(headless)
puppeteer 運行chromium 在headless模式下. 當運行瀏覽器時設置'headless' 選項使chromium運行在全模式下.
const browser = await puppeteer.launch({headless: false});
- 綁定特定版本的chromium
預設情況下,puppeteer下載使用指定版本的 chromium 以保證所有的API正常工作. 創建Browser實例時指定 executablePath值來以使用不同瀏覽器.
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'})
查看puppeteer.launch() API瞭解更多信息.
閱讀這篇文章瞭解chromium和 Chrome 的不同, 描述了Chrome和 chromium 在Linux下的不同.
- 創建一個新用戶
puppeteer每次運行時先創建一個 chromium 用戶, 運行結束後就清除用戶信息.
API文檔
探索API 文檔和例子來學習更多.
調試技巧
- 關閉無頭模式 - 有時觀看瀏覽器的顯示是有用的. 使瀏覽器運行在全模式而不是無頭模式下, 使用headless: false:
const browser = await puppeteer.launch({headless: false,})
- 慢下來 - slowMo 選項減慢puppeteer 執行速度, 減慢指定的總毫秒數. 這是幫助觀察發生什麼的另一個途徑.
const browser = await puppeteer.launch({
headless: false,
slowMo: 250 //減慢puppeteer 250ms
});
- 捕獲控制台輸出 - 監聽console事件. 當調試page.evaluate() 內部代碼時比較便利.
page.on('console', msg => console.log('頁面log', msg.text()));
await page.evaluate(() => console.log(`url is ${location.href}`))
- 停止執行測試,在瀏覽器內使用debugger
- 運行puppeteer時使用 {devtools: true}:
const browser = await puppeteer.launch({devtools: true});
- 改變測試超時時間:
- jest:
jest.setTimeout(100000);
- jasmine:
jasmine.DEFAULT_TIME_INTERVAL = 100000;
- mocha:
this.timeout(100000);
(改變測試時使用 function 不能使用箭頭函數)
- jest:
- 在evaluate內部使用
debugger
語句, 在已存在的evaluate環境中添加debugger
await page.evaluate(() => {
debugger;
});
puppeteer測試將會停止在上面這條語句, chromium也將停留在 debugger 模式.
- 打開詳細記錄 - 調用所有公共API 和內部傳輸協議將會被
puppeteer
命名空間下的debug
模塊記錄
# 基本的詳細記錄
env DEBUG="puppeteer:*" node script.js
# 調試輸出可通過命名空間來開關
env DEBUG="puppeteer:*,-puppeteer:protocol" node script.js # 記錄除了協議信息的所有信息
env DEBUG="puppeteer:session" node script.js # 記錄會話協議(protocol messages)
env DEBUG="puppeteer:mouse,puppeteer:keyboard" node script.js # 只記錄滑鼠和鍵盤API調用
# 傳輸協議記錄的比較繁雜. 下麵例子過濾所有網路信息.
env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
為puppeteer貢獻
查看貢獻指南 以瞭解puppeteer開發概述
FAQ(常見問題)
誰維護puppeteer?
Chrome DevTools團隊維護這個庫, 同時歡迎大家的參與!
puppeteer的目標和職責是什麼?
這個項目的目標是:
- 提供一個精簡和權威的庫以突出 DevTools Protocol 的能力
- 為類似的測試庫提供實現參考. 最終其它框架可以採用puppeteer作為基礎層.
- 發展採用 無頭,自動化 瀏覽器測試.
- 幫助DevTools Protocol 新特性做 dogfood 測試, 捕獲bug
- 尋找瀏覽器自動化測試的痛點, 然後幫助解決這些差別.
我們採用chromium職責來幫助我們驅動產品做決定:
- 快速: puppeteer在一個自動化測試頁面的性能開銷幾乎為0.
- 安全: puppeteer在 Chromium 操作過程中,自動使潛在的惡意頁面安全.
- 穩定: puppeteer不是脆弱的,也不會有記憶體泄漏
- 簡易: puppeteer 提供易用易理解和調試的高級API.
Puppeteer是用來取代Selenium/webDriver的嗎?
不是, 這兩個項目因為一些不同的原因都是有價值的.
- Selenium/WebDriver 集中於自動跨瀏覽器; 它的價值在於提供一個在所有主要瀏覽器里工作的單一標準API.
- Puppeteer 專註於Chromium;它的價值在於豐富的功能和高可靠性.
也就是說,你可以使用puppeteer在非Chromium瀏覽器里運行測試. 例如使用community-driver jest-puppeteer. 雖然puppeteer不是你唯一可用的解決方案,但確實有幾分比web Driver好的特點: - puppeteer 可以零設置,附帶特定版本的chromium是其更好的工作,puppeteer開始使用非常容易,在一天結束時只在chromium上運行幾個測試比不測試好.
- puppeteer 是事件驅動架構, 移除大量潛在脆弱環節. 不需要在puppeteer腳本調用邪惡的"sleep(1000)"
- puppeteer 預設運行在headless模式下,使得啟動非常快. puppeteer V1.5.0 也暴露出瀏覽器上下文, 使高效的並行執行測試成為可能.
- puppeteer 在調試時高亮: 翻轉headless位 false ,設置slowMo選項, 將會看到瀏覽器的行為. 甚至可以打開Chrome DevTools來檢查測試環境.
為什麼puppeteer V.xxx 不能和Chromium V.yyy一同工作?
puppeteer作為 chromium 不可分割的一部分. 每個版本的puppeteer綁定於一個特定版本的 chromium以保證 puppeteer工作.
著並不是通過人工來約束,許多puppeteer工作確實在 chromium 倉庫里.下麵時典型故事:
- puppeteer bug報告 https://github.com/GoogleChrome/puppeteer/issues/2709
- 這原本是DevTools protocol的 issue, 然後在chromium里修複 https://chromium-review.googlesource.com/c/chromium/src/+/1102154
- 當bug修複後,滾動更新chromium到 puppeteer
然而,通常人們更願意將puppeteer 和官方的Google Chrome一同使用.這種情況下需要選擇特定版本的puppeteer以使chromium版本接近chrome.
puppeteer使用哪個版本的 chromium?
在puppeteer相關版本的package.json文件里查看.
什麼是導航(navigation)?
在puppeteer觀點中, '導航(navigation)' 是所有改變頁面URL的事物. 除了常規的導航外,在瀏覽器中點擊網路從web伺服器中獲取新文檔, 包含a標簽導航和history API
在這個navigation定義中, puppeteer和單頁面應用無縫銜接.
信任的和不信任的輸入事件有什麼不同?
在瀏覽器中輸入事件被分為兩大類: 信任的和不被信任的.
- 信任事件: 通過頁面的用戶介面產生. 例如使用滑鼠和鍵盤.
- 非信任事件: 通過web API產生. 例如document.createEvent 或者 element.click() 方法.
網站能夠區分這兩類事件:
- 使用
Event.isTrusted
事件標誌. - 嗅探伴隨事件. 例如每一個可信任的點擊事件之前都是'moussedown' 和'mouseup'事件.
為了自動化的目的, 生成可信任事件是比較重要的. 通過puppeteer生成的輸入事件都是可信任事件和觸發適當的伴隨事件.如果需要非信任事件,需要通過page.evaluate
在頁面上下文中生成模擬事件:
await page.evaluate(() => {
document.querySelector('button[type=submit]').click();
})
puppeteer不支持什麼特性?
你也許會發現當puppeteer控制包含audio和video的頁面時一些行為不是預期的.(例如, 視頻播放時截圖會失敗), 這有以下兩個原因:
- Puppeteer 是和chromium綁定的,並不是chrome, 所以puppeteer繼承了 chromium所有限制. 這意味著puppeteer 不支持一些許可格式例如: AAC和 H.264(然而也可能強制puppeteer使用, 當 通過executablePath選項使用chrome替代chromium時. 只有在官方發佈的chrome支持這些媒體格式時才能使用這些配置)
- 自從puppeteer控制chromium/chrome的桌面版後,只在手機版本里的chrome特性不被支持. 這意味著puppeteer不支持 http Live Streaming(HLS).
在測試環境中安裝運行puppeteer時存在問題?
我們有一份針對不同操作系統的排錯指南需求列表.
如何使用puppeteer的提前版本?
npm i --save puppeteer@next
提示: 提前版本可能不穩定和包含bugs.
還有更多問題,到哪裡尋求幫助?
這裡有許多關於puppeteer幫助的路徑:
確保在提交你的問題之前在這些頻道里搜索問題.