概要

みなさんはWebスクレイピングをしたいと思ったことはありますか?

私は、今回Web上に分散したデータを集めたいということがあったので、Webスクレイピングをやってみました。

そもそもWebスクレイピングをやることにした理由は、データ自体がかなり分散していたため、アクセスをする場所も多く、手作業でやるのは現実的でないということが一番の理由です。

ここでは、私がWebスクレイピングをする際に使ったPuppeteerを紹介したいと思います。

環境

  • Node.js 15
  • Puppeteer 5.5

Puppeteerを選択した理由

Webスクレイピングをする方法にはいくつかありますが、Puppeteerの特徴的な点として、Chromiumを使って実際にWebページをレンダリングするということがあります。

いままでのスクレイピングでは、URLを指定してHTMLを取得した後に、そのHTMLをパースしてほしいデータを見つけるということが一般的でした。例えば表データであれば、HTMLのtableタグの内容をパースしてデータを取り出すという流れです。

HTMLのパースによる方法はオーバーヘッドが少なく、リソースが少なくても良いのですが、SPAのようなレンダリングをすることでしかデータを取り出すことしかできないようなWebページにも対応できるというメリットがあります。

また、私が特に良いと思っている点として、データの取得にDOMによるアクセスが使えるということがあります。DOMによるアクセスはJavaScript等でWebページの操作をする場合には、よく使われるものなので、そのような作業を普段からしている場合には、HTMLをパースするよりも楽にデータの取得ができます。

何よりもPuppeteerは、パースに正規表現を使わなくてもよいというのがよいです。正規表現を使ったデータ取得が面倒という場合に、特におすすめです。

インストール

Puppeteerは、Node.jsのライブラリとして使うものとなっているので、最初にNode.jsをインストールしましょう。

Node.jsのインストールについては、様々な場所に公開されているので、それらを参考にインストールしましょう。

Puppeteerのインストールは次のコマンドでできます。

$ npm install -g puppeteer

これで、準備は完了です。

スクレイピング

実際にスクレイピングをやってみたスクリプトが次になります。

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();

    const page = await browser.newPage();

    const url = 'https://www.yahoo.co.jp';
    await page.goto(url);

    // 複数のURLにアクセスするときはこれを使って短期間に大量のアクセスをしないようにする
    await page.waitForTimeout(1000); // 1

    // $evalの引数にDOMを取得するような形で値を取得する要素を指定
    // 無名関数で要素から値を取り出す
    let data = await page.$eval('.content', item => item.textContent);
    console.log(data);
})();

他にも、要素を選択してクリックしたり、リンクをクリックして遷移したりもできますが、今回私は使わなかったので、ここには書いていません。また、URLや要素の指定は適当なので、その都度変更してください。

Puppeteerではconst browser = puppeteer.launch()でpuppeteerを起動して、const page = browser.newPage()で実際にレンダリングをするページを作成します。page.goto(url)で、指定したURLへのアクセスをしてレンダリングをしてくれるので、これで、データを取得したいページの準備は完了です。最後にpage.$evalでDOMから値を取り出すことができます。

なんとなく雰囲気をつかめたのではないでしょうか。JavaScriptを普段から使ってるようなWebに関わっている人は、みてすぐにやっていることが分かるのではないかと思います。

さいごに

Puppeteerは、Webスクレイピングが非常にやりやすいと思います。

Node.jsやJavaScriptを使いたくないなどの理由がない限りは、Puppeteerを使うことをすすめます。