LoginSignup
17
19

More than 5 years have passed since last update.

Chrome操作ライブラリ「Puppeteer」でスクレイピングしてみた

Posted at

はじめに

Headless ChromeをNode.js上で操作するライブラリにPuppeteerがあります(しかもGoogle製!)。
これがスクレイピングツールとしても使えそうなので、試しにWikipediaからタイトル、本文、画像を取ってみました。

インストール手順

OS : Windows10
Puppeteerのバージョン : 1.5.0

インストールは以下のコマンドを打つだけです。

Puppeteerのインストール
$ npm install puppeteer

※事前にNode.jsとnpmをインストールする必要があります。

ソースコード(全体)

crawler.js
const puppeteer = require('puppeteer');

(async () => {
  // const browser = await puppeteer.launch();
  const browser = await puppeteer.launch({ headless: false }); // ヘッドレスにしない


  const page = await browser.newPage();

  const url = 'https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%87%E3%83%AA%E3%83%BC%E3%83%9A%E3%83%B3%E3%82%AE%E3%83%B3';
  await page.goto(url, { waitUntil: 'domcontentloaded' }); // domを読み込むまで待機

  // タブを移動
  const pages = await browser.pages();
  const detailPage = pages[1];
  await detailPage.bringToFront();

  // タイトル取得
  let selector = '#firstHeading';
  const titleDom = await detailPage.$(selector);
  if (titleDom) {
    title = await detailPage.$eval(selector, e => e.textContent);
    console.log(title);
  }

  // 本文取得
  selector = '#mw-content-text > div > p';
  const contentDom = await detailPage.$$(selector);
  if (contentDom.length > 0) {
    content = await detailPage.$$eval(selector, elements => {
      let datas = [];
      for (e of elements) {
        datas.push(e.textContent);
      }
      return datas;
    });
    for (c of content) {
      console.log(content);
    }
  }

  // 画像取得
  selector = '#mw-content-text > div > table.infobox.bordered > tbody > tr:nth-child(2) > td > a > img';
  const dom = await page.$(selector);
  if (dom) {
    await dom.screenshot({ path: 'penguin.png' });
  }

  await browser.close();
})();

ソースコード(詳細)

覚えておいたほうがよさそうなところだけメモ。

読み込むまで待機

page.goto()でページ遷移する際に、waitUntilでページのロードを待機します。

  • domcontentloadedにすれば、htmlを読み込むまで待機
  • loadにすれば、その後画像を読み込むまで待機
  • networkidle0にすれば、500ミリ秒コネクションがなくなるまで待機

JavaScriptを読み込むまで待とうと思ったら、networkidle0がよさげ?
networkidle2ってのもある模様。

読み込むまで待機
await page.goto(url, { waitUntil: 'load' });

タブの移動

リンクをクリックすると、新規タブに移動される場合があります。
その場合はそのタブに移動する必要があります(今回のソースではいらないけど・・・)。

タブの移動
const pages = await browser.pages();
const detailPage = pages[1];
await detailPage.bringToFront();

スクレイピング

テキストや属性を取得するときは、基本この書き方だと思います。
この例だとtextContentを指定しているので要素内のテキストを取得します。

スクレイピング
title = await detailPage.$eval(selector, e => e.textContent);

画像の取得

DOMに対してもスクリーンショットが取れます。もちろんページにも取れます。

画像の取得
await dom.screenshot({ path: 'penguin.png' });

実行

起動
$ node crawler.js

penguin.png

なんか、画像がうまく取れませんでした・・・。
こういう時は、画像のURLにアクセスしてからpage.screenshot()をするとよさそうです。

おわりに

割と簡単で便利でした。
PuppeteerはAPIの種類がかなり多いので、色々試してみるのも面白そうですが、公式のAPIドキュメントを呼んでもよく分からないところもまだありますね・・・。

17
19
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
17
19