Puppeteerのpage.evaluateとpage.$はどちらがいいか

疑問

スクレイピングではPuppeteerをよく使うのだが、page.evaluate()page.$()の違いがよく分からなかった。

ちなみに、自分はpage.evaluate()しか使ったことがない。

回答

何が違うのか、どちらを使うべきか、その疑問が以下リンクを見つけて解決した。

stackoverflow.com

質問者も同じ疑問を持っており、page.evaluate()のほうが作業しやすい、と意見している。

回答が素晴らしいのでまとめてみた。

以下、日本語訳した回答↓↓↓

これらのコード行の主な違いは、Node.jsとブラウザー環境の間の相互作用です。

page.evaluate()は次のことを行います。

  • document.querySelectorブラウザーで実行し、要素ハンドルを(Node.js環境に)返します
  • getPropertyハンドルで実行し、結果を(Node.js環境に)返します
  • ブラウザ内の要素をクリックします

page.$()は単にこれを行います。

  • ブラウザーコンテキストで指定された関数を実行します(そして結果をNode.js環境に返します)

性能

これらのステートメントのパフォーマンスに関して、PuppeteerはWebSocketsを介してブラウザと通信することを覚えておく必要があります。したがって、ブラウザに送信されるコマンドは1つだけなので(2つとは対照的に)、2番目のステートメントは高速に実行されます。

接続しているブラウザが別のマシンで実行されている場合(を使用して接続されている場合puppeteer.connect)、これは大きな違いをもたらす可能性があります。スクリプトとブラウザが同じマシン上にある場合、わずか数ミリ秒の差が生じる可能性があります。したがって、後者の場合、大きな違いはないかもしれません。

ElementHandlを使用する利点

ElementHandleを使用すると、いくつかの利点があります。まず、のような関数elementHandle.clickは、を使用するのとは対照的に、より「人間らしい」動作をしdocument.querySelector('...').click()ます。puppeteerは、たとえば、click関数を実行するだけでなく、マウスをその場所に移動し、要素の中央をクリックします。

何を使用するか

一般に、page.evaluateこのAPIデバッグもはるかに簡単なので、可能な限り使用することをお勧めします。エラーが発生した場合、ChromeブラウザーでDevToolsを開き、ブラウザーで同じ行を再実行することにより、エラーを簡単に再現できます。多数のpage.$ステートメントを一緒に混在させている場合、問題が何であるか、Node.jsまたはブラウザーランタイム内で発生したかどうかを理解することははるかに困難です。

要素をより長く必要とする場合は、要素ハンドルを使用します(複雑な計算を行ったり、外部イベントから情報を抽出する前に外部イベントを待機した可能性があるため)。

結論

  • page.evaluateを使おう
  • デバッグもエラー再現も簡単