LoginSignup
5
2

More than 1 year has passed since last update.

Hurry Puppeteer とのろいの子

Last updated at Posted at 2022-12-04

このタイトル思いついて書いてみたのであとは蛇足みたいなものですが。

Headless Chromeを操作できるNode.jsのライブラリのPuppeteerで重いサイトを快速に使える方法がないか調べてみたがうまいこといかなかった話です。

waitUntilの待つタイミングを調整する

await page.goto(TARGET_URL, {waitUntil: 'domcontentloaded'});

取得完了とみなすタイミングを調整する。これが一番効果があったように思えます。
loadだと画像を含めてページの読込みが全て完了した時点を完了としますが、domcontentloadedだとHTMLの解析が完了した時点で完了となる。

ただし、画像まで必要な場合や、外部リソースを取り込んで遅延で描画が行われるなど、domcontentloadedの時点だとダメな場合もあるので、必要に応じて設定が必要になる。

内容
load ローディングの完了時点
domcontentloaded HTMLの読み込みと解析が完了時点
networkidle0 500ms以上ネットワーク接続が無い
networkidle2 500ms以上ネットワーク接続が2件以下

Chromeの起動パラメーターを調整する。

Run Puppeteer with Minimal Settings
にあるように、Chromeの起動パラメーターを最小限の設定にすることが出来る。
--no-sandboxが効果がありそうだが、セキュリティ上のリスクもあるので、サイトによって使い分けが必要。 
いろいろ試してみたが実感するほど差はなかったので、やみくも付けるのではなく、都度試しながらした方が良さそう。

const puppeteer = require('puppeteer');

const options = [
  '--autoplay-policy=user-gesture-required',
  '--disable-background-networking',
  '--disable-background-timer-throttling',
  '--disable-backgrounding-occluded-windows',
  '--disable-breakpad',
  '--disable-client-side-phishing-detection',
  '--disable-component-update',
  '--disable-default-apps',
  '--disable-dev-shm-usage',
  '--disable-domain-reliability',
  '--disable-extensions',
  '--disable-features=AudioServiceOutOfProcess',
  '--disable-hang-monitor',
  '--disable-ipc-flooding-protection',
  '--disable-notifications',
  '--disable-offer-store-unmasked-wallet-cards',
  '--disable-popup-blocking',
  '--disable-print-preview',
  '--disable-prompt-on-repost',
  '--disable-renderer-backgrounding',
  '--disable-setuid-sandbox',
  '--disable-speech-api',
  '--disable-sync',
  '--hide-scrollbars',
  '--ignore-gpu-blacklist',
  '--metrics-recording-only',
  '--mute-audio',
  '--no-default-browser-check',
  '--no-first-run',
  '--no-pings',
  '--no-sandbox',
  '--no-zygote',
  '--password-store=basic',
  '--use-gl=swiftshader',
  '--use-mock-keychain',
];

  
(async () => {
const startTime = performance.now();
const browser = await puppeteer.launch({
    headless: true,
    args: options
  })
  
const page = await browser.newPage();
await page.goto('https://ja.wikipedia.org/wiki/');
await browser.close();

const endTime = performance.now();
console.log(endTime - startTime); 
})();

ユーザーデータの保存先を指定する

Cache Resources with userDataDir
によると、userDataDirパスを指定しないと、CSSなどのキャッシュが効かないので指定するようにした方が良いとのこと。

const browser = await puppeteer.launch({
  userDataDir: './my/path'
}

画像の読み込みをブロックする

画像を読み込む必要がなければ、setRequestInterceptionを使って
不要なリクエストをabortすることが出来る。
画像(image)、CSS(stylesheet)、フォント(font), スクリプト(script)などの指定や
特定のドメインの除外なども出来る。
もしくは(document)だけで絞ることも可能。
画像が多いサイトであれば数秒の短縮はできるが、画像がないと思った通りの操作が出来ないケースもあったので、条件によって使い分けが必要か。


const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.setRequestInterception(true)
  page.on('request', async (request) => {
    if (request.resourceType() == 'image') {
      await request.abort()
    } else {
      await request.continue()
    }
  })
  await page.setViewport({ width: 1280, height: 800 })
  await page.goto('https://www.nytimes.com/')
  await page.screenshot({ path: 'nytimes.png', fullPage: true })
  await browser.close()
})()

プロセスのクローズし忘れない

エラーが発生した際にbrowser.close()をするのを忘れていたらプロセスがたまってしまうので、browser.close()を入れ忘れないようにする。

そもそもヘッドレスブラウザを使わない

HTMLを直接読み込んで解析した方が明らかに速いので、
場面によっては、ヘッドレスブラウザと使い分けて使用した方が良さそう。

const axios = require('axios');
const { JSDOM } = require('jsdom');

(async () => {
    const res = await axios.get("https://ja.wikipedia.org/wiki/");
    const { data } = res;
    const dom = new JSDOM(data);
    const selector = '#welcome';
console.log(dom.window.document.querySelector(selector).textContent);
})();

結果

参考サイトだと効果があった書かれてあったが、自分が試したサイトだとそこまで効果を感じなかった。
一律でこれを設定すればOKみたいなものはなさそう。
該当のサイトで何の操作をしたいのか、サイトがどうやって描画されているかや(JavaScript等々)を調べてからサイト別にチューニングが必要になってきそうです。

その他参考サイト

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2