無頭瀏覽器實做筆記

無頭瀏覽器(headless browser),簡單來說,就是沒有 GUI 介面的瀏覽器。如果我們的程式需要瀏覽器的功能:比方說不開瀏覽器截圖(比方說,有網站提供預覽功能?)、載入單頁應用(SPA)……那我們就會考慮無頭瀏覽器。

這裡使用 puppeteer 為範例。

感想……唉,太肥了。光抓一次 puppeteer 就要花去幾分鐘的時間,實在是提不起勁玩無頭瀏覽器啊……

如何截圖?

import { launch } from "puppeteer";

const main = async () => {
    // Init
    const browser = await launch();
    const page = await browser.newPage();
    // Settings
    await page.setViewport({
        width: 1800,
        height: 1024,
        deviceScaleFactor: 1,
    });
    await page.goto("https://github.com/");
    await page.screenshot({
        path: "result.png",
    });
    await browser.close();
};

main();

如何輸出載入該網頁的資源,比方說 CSS, JavaScript, 圖片等檔案?

如何輸出 SPA 專案會用到的 JSON 檔案?

看了 pixeljets 的範例後才知道訣竅。

於是我就這麼做了:

import { launch } from "puppeteer";
import fs from "fs";

const main = async () => {
    const input = "toyota";
    // Browser opreation part
    const browser = await launch();
    const page = await browser.newPage();
    // Init page
    await page.goto("https://apiroad.net/ajax-test.html");
    // Input form
    await page.waitForSelector("form > input[type=text]");
    await page.type("form > input[type=text]", input);
    page.click("#search-button");
    // JSON render
    const cb = the =>
        the.request().url().includes("sample-search.php") &&
        the.request().method() != "OPTIONS"
    ;
    const xhrCatcher = page.waitForResponse( cb );
    // Get JSON
    const xhrResponse = await xhrCatcher;
    const xhrPayload = await xhrResponse.json();
    console.log( xhrPayload );
    await browser.close();
};

main();

先連到網站後,輸入表單並送出資料。而所有回應則使用 waitForResponse 方法,針對連結做對應的過濾判斷,找到與 API 相符的回應後,把回應抓下來。

如何以會員身份抓資料?

幾個想法:

  1. Cookie
  2. JWT Token