踏入 headless Chrome 新世界,使用 Puppeteer 抓取網頁截圖

之前使用 PhantomJS 的時候,遇到好多莫名其妙的 Bug,實在很雷啊,所以我就寫了篇文章,記錄當時的使用心得、分享網頁截圖的方法。

雖然當時 Google 已經推出了 headless Chrome ,也提供網頁截圖的範例程式,不過由於剛起步,使用上還不如 PhantomJS 這麼方便,我玩沒幾下就作罷了。

然而在今年 8 月,Google 終於推出了 Puppeteer 這套基於 NodeJS 的 Library,讓我們能輕易地操作 headless Chrome,而且範例全都是用 async/await 的方式來撰寫,比起以前看 PhantomJS 要來的易讀許多 XD

廢話不多說,就讓我們來看看 Puppeteer 有什麼特別之處吧。


什麼是 Puppeteer?

puppeteer - 踏入 headless Chrome 新世界,使用 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 的組合根本超猛阿。

  1. Turn off headless mode (打開 Chrome,讓你看到運作的情況)
  2. Slow it down (放慢執行的速度)
  3. Capture console output
  4. Enable verbose logging

詳盡的使用方法請參考 GitHub Repo 以及 API 文件囉。

Puppeteer GitHub
Puppeteer API

參考資料

Jerry
Jerry

樂於分享的軟體工程師,曾在新創與大型科技公司實習,獲得黑客松競賽冠軍,擔任資安研討會講者。長期熱衷於資訊安全、雲端服務、網路行銷等領域,希望將科技知識分享給更多人。內容轉載請來信:jlee58tw@gmail.com

發表回應