之前使用 PhantomJS 的時候,遇到好多莫名其妙的 Bug,實在很雷啊,所以我就寫了篇文章,記錄當時的使用心得、分享網頁截圖的方法。
雖然當時 Google 已經推出了 headless Chrome ,也提供網頁截圖的範例程式,不過由於剛起步,使用上還不如 PhantomJS 這麼方便,我玩沒幾下就作罷了。
然而在今年 8 月,Google 終於推出了 Puppeteer 這套基於 NodeJS 的 Library,讓我們能輕易地操作 headless Chrome,而且範例全都是用 async/await 的方式來撰寫,比起以前看 PhantomJS 要來的易讀許多 XD
廢話不多說,就讓我們來看看 Puppeteer 有什麼特別之處吧。
什麼是 Puppeteer?
根據 GitHub 上的描述,Puppeteer 是一個讓你能夠透過 API 輕易操作無介面瀏覽器的工具,重點就是 API 與無介面瀏覽器呀!
Puppeteer is a Node library which provides a high-level API to control headless Chrome over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome.
以往我們爬取資料或是進行自動化測試的時候,會使用 Selenium 這類自動化工具,但是這些工具並不是在背景模擬操作,而是透過 Driver 實際控制你的瀏覽器。所以當他在自動運作的時候,我們不能去打擾他,就像是兩個人無法同時控制一隻滑鼠,如果你移動了,接下來他的動作可能就會出錯。
因為需要開瀏覽器,讓測試不容易平行擴展,所以後來有了 PhantomJS 這樣的無介面瀏覽器框架,方便我們進行自動化操作。也因為所有的操作都是透過 API 控制,在背景裡默默執行,所以我們不用擔心干擾的問題。
不過 PhantomJS 問題還挺多,是時候該老大哥出馬了 XD
接下來的故事大家就知道了,Google 在自家的瀏覽器 Chrome 推出 headless 功能,解決了無介面瀏覽器問題,同時推出了這個 Puppeteer,並以開源方式釋出,就是希望借助廣大的社群力量,讓他變得更好,在測試工具大戰中生存下來。
安裝與環境設定
Puppeteer 至少需要 Node v6.4.0 版本,但因為範例採用了 async/await,所以還是建議升級至 Node v7.6.0 以上。安裝時間有點久,因為他會順便下載 Chromium。
yarn add puppeteer
螢幕截圖
進行螢幕截圖非常簡單,指定個路徑跟儲存位置就行了,預設是以電腦版 800*600 解析度開啟。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://google.com');
await page.screenshot({path: 'test.png'});
await browser.close();
})();
假如我們要模擬手機來開網頁該怎麼做呢?
Puppeter 已經貼心的訂製好一份裝置規格表「DeviceDescriptors」,假如我要模擬 iPhone 6,直接匯入參數來進行模擬就行了。
const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://yahoo.com.tw');
await page.screenshot({path: 'test.png'});
await browser.close();
})();
但這個規格表也只有特定幾個機型,像是 iPhone X 就沒有哈哈,如果想要其他規格的話,就需要自行設定。可以試著調整 viewport 以及 useragent。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const viewport = {
width: 375,
height: 667,
isMobile: true,
hasTouch: true,
};
const userAgent = "hello! I am a robot";
await page.setUserAgent(userAgent);
await page.setViewport(viewport);
await page.goto('https://google.com');
await page.screenshot({path: 'test.png'});
await browser.close();
})();
開發除錯
之前使用 PhantomJS 最麻煩的地方就在於不好 Debug,還好 Puppeteer 提供滿多除錯的方法與指引,1 和 2 的組合根本超猛阿。
- Turn off headless mode (打開 Chrome,讓你看到運作的情況)
- Slow it down (放慢執行的速度)
- Capture console output
- Enable verbose logging
詳盡的使用方法請參考 GitHub Repo 以及 API 文件囉。
Puppeteer GitHub Puppeteer API