Puppeteer 是 Chrome 開發團隊在 2017 年發布的一個 Node.js 包,用來模擬 Chrome 瀏覽器的運行。功能比PhantomJs 要強大很多。 
        
 
         
         一、什么是 Chrome DevTool Protocol 
        
 
         
         1.CDP 基於 WebSocket,利用 WebSocket 實現與瀏覽器內核的快速數據通道 
        
 
         
         2.CDP 分為多個域(DOM,Debugger,Network,Profiler,Console...),每個域中都定義了相關的命令和事件(Commands and Events) 
        
 
         
         3.我們可以基於 CDP 封裝一些工具對 Chrome 瀏覽器進行調試及分析,比如我們常用的 “Chrome 開發者工具” 就是基於 CDP 實現的 
        
 
         
         4.如果你以 remote-debugging-port 參數啟動 Chrome,那么就可以看到所有 Tab 頁面的開發者調試前端頁面,還會在同一端口上還提供了 http 服務,主要提供以下幾個接口: 
        
 
         
         
         
         GET /json/version # 獲取瀏覽器的一些元信息 GET /json or /json/list # 當前瀏覽器上打開的一些頁面信息 GET /json/protocol # 獲取當前 CDP 的協議信息 GET /json/new?{url} # 開啟一共新的 Tab 頁面 GET /json/activate/{targetId} # 激活某個頁面成為當前顯示的頁面 GET /json/close/{targetId} # 關閉某個頁面 GET /devtools/inspector.html # 打開當前頁面的開發者調試工具 WebSocket /devtools/page/{targetId} # 獲取某個頁面的 websocket 地址 
        
 
         
         5.很多有用的工具都是基於 CDP 實現的,比如 Chrome 開發者工具,chrome-remote-interface,Puppeteer 等 
        
 
         
         二、什么是 Headless Chrome 
        
 
        - 在無界面的環境中運行 Chrome
 - 通過命令行或者程序語言操作 Chrome
 - 無需人的干預,運行更穩定
 - 在啟動 Chrome 時添加參數 --headless,便可以 headless 模式啟動 Chrome
 
 
         # Mac OS X 命令別名 
        
 
         
         alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome" 
        
 
         
         # 開啟遠 程調試  
        
 
         
         chrome --headless --remote-debugging-port=9222 --disable-gpu 
        
 
         
         # 獲取頁面  
        
 
         
         DOM chrome --headless --disable-gpu --dump-dom https://www.baidu.com 
        
 
         
         # 截圖  
        
 
         
         chrome --headless --disable-gpu --screenshot https://www.baidu.com 
        
 
         
         chrome 啟動時可以加一些什么參數,大家可以點擊這里查看 
        
 
         
         三、Puppeteer 是什么 
        
 
        - Puppeteer 是 Node.js 工具引擎
 - Puppeteer 提供了一系列 API,通過 Chrome DevTools Protocol 協議控制 Chromium/Chrome 瀏覽器的行為
 - Puppeteer 默認情況下是以 headless 啟動 Chrome 的,也可以通過參數控制啟動有界面的 Chrome
 - Puppeteer 默認綁定最新的 Chromium 版本,也可以自己設置不同版本的綁定
 - Puppeteer 讓我們不需要了解太多的底層 CDP 協議實現與瀏覽器的通信
 
 
         四、Puppeteer 能做什么 
        
 
        - 網頁截圖或者生成 PDF
 - 爬取 SPA 或 SSR 網站
 - UI 自動化測試,模擬表單提交,鍵盤輸入,點擊等行為
 - 捕獲網站的時間線,幫助診斷性能問題
 - 創建一個最新的自動化測試環境,使用最新的 js 和最新的 Chrome 瀏覽器運行測試用例
 - 測試 Chrome 擴展程序
 
 
         五、Puppeteer API 分層結構 
        
 
         
         Puppeteer 中的 API 分層結構基本和瀏覽器保持一致,下面對常使用到的幾個類介紹一下: 
        
 
        
 
        
 
         
         Browser: 
        
 
         
         對應一個瀏覽器實例,一個 Browser 可以包含多個 BrowserContext 
        
 
         
         BrowserContext: 
        
 
         
         對應瀏覽器一個上下文會話,就像我們打開一個普通的 Chrome 之后又打開一個隱身模式的瀏覽器一樣,BrowserContext 具有獨立的 Session(cookie 和 cache 獨立不共享),一個 BrowserContext 可以包含多個 Page 
        
 
         
         
         
         Page: 
        
 
         
         表示一個 Tab 頁面,通過 browserContext.newPage()/browser.newPage() 創建,browser.newPage() 創建頁面時會使用默認的 BrowserContext,一個 Page 可以包含多個 Frame 
        
 
         
         Frame: 
        
 
         
         一個框架,每個頁面有一個主框架(page.MainFrame()),也可以多個子框架,主要由 iframe 標簽創建產生的 
        
 
         
         ExecutionContext: 
        
 
         
         是 javascript 的執行環境,每一個 Frame 都一個默認的 javascript 執行環境 
        
 
         
         ElementHandle: 
        
 
         
         對應 DOM 的一個元素節點,通過該該實例可以實現對元素的點擊,填寫表單等行為,我們可以通過選擇器,xPath 等來獲取對應的元素 
        
 
         
         JsHandle: 
        
 
         
         對應 DOM 中的 javascript 對象,ElementHandle 繼承於 JsHandle,由於我們無法直接操作 DOM 中對象,所以封裝成 JsHandle 來實現相關功能 
        
 
         
         CDPSession: 
        
 
         
         可以直接與原生的 CDP 進行通信,通過 session.send 函數直接發消息,通過 session.on 接收消息,可以實現 Puppeteer API 中沒有涉及的功能 
        
 
         
         Coverage: 
        
 
         
         獲取 JavaScript 和 CSS 代碼覆蓋率 
        
 
         
         Tracing: 
        
 
         
         抓取性能數據進行分析 
        
 
         
         Response: 
        
 
         
         頁面收到的響應 
        
 
         
         Request: 
        
 
         
         頁面發出的請求 
        
 
         
         六、兩個獨立的環境 
        
 
         
         使用 Puppeteer 時其實是這兩個環境之間交換數據:運行 Puppeteer 的 Node.js 環境和 Puppeteer 操作的頁面 Page DOM,理解這兩個環境很重要 
        
 
        - 首先 Puppeteer 提供了很多有用的函數去 Page DOM Environment 中執行代碼
 - 其次 Puppeteer 提供了 ElementHandle 和 JsHandle 將 Page DOM Environment 中元素和對象封裝成對應的 Node.js 對象,這樣可以直接這些對象的封裝函數進行操作 Page DOM
 
