新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

puppeteerの使い方メモ

以前、SeleniumとPlaywrightの比較のため両方を検証していました。せっかく使い方を覚えたので、また必要になった時にすぐに思い出せるよう下記記事に簡単に使い方をまとめました。

元々クローラーとしてpuppeteerを使っていたので、Selenium・Playwrightをまとめたのなら、puppeteerは外せないでしょということで、ここにpuppeteerの使い方を簡単にまとめてみることにしました。

ただ、SeleniumとPlaywrightを検証した結果、今はPlaywrightをメインで使っています。なので、通常使いの向けの網羅的なまとめではなく、puppeteerのお作法について簡単にまとめたものに留めておこうと思います。

インストール

npm install --save puppeteer
  • ブラウザChromiumがnode_modulesにインストールされ、そのブラウザが使われる
  • ブラウザはpuppeteerがインストールしたものではなく、自分で用意したものも使える。その場合は、executablePathを設定する
  • ブラウザをインストールしたくない場合はpuppeteer-coreをインストールする

自分が用意したブラウザを使う

npm install --save puppetter-core
const browser = await puppeteer.launch({executablePath: <browser_path>});

サンプル

例)Googleで「test」と検索し、結果ページのソースを表示する。

import puppeteer from 'puppeteer';

(async () => {
    try {
        const browser = await puppeteer.launch({
            headless: false,
            slowMo: 100,
        });

        const page = await browser.newPage();

        let selector;

        await page.goto("https://www.google.com");

        selector = 'input[name="q"]';
        await page.waitForSelector(selector);
        await page.type(selector, "test\n");

        await page.waitForNavigation();

        console.log(await page.content());

    } catch (err) {
        console.error(err);
    }
})();

puppeteerの仕組みと流れ

  • ブラウザ操作の流れは、対象となるdomを取得し、そのdomに対して操作の繰り返しになる。
  • domは動的に生成されることがあるので、domを取得しようとした時にまだ生成されていない時がある。なので、dom取得はdomが存在するのを確認してから行う必要がある。domが見つかるまで待つのがpage.waitForSelector()
  • domが見つかると、そのdomに対してブラウザ上でJavaScriptを実行することによりdomを操作する

ボタンをクリックする場合下記のようになる。

  • page.$eval()は、第2引数のJavaScript関数を、ブラウザ上で実行してくれる
  • page.$eval()の第1引数で指定したセレクターのdomが、第2引数のdomとなる
let selector = 'input[type="button"]';
await page.waitForSelector(selector);
await page.$eval(selector, dom=>{ dom.click() });

pageには、よくやるJavaScript操作のいくつかが関数にまとめられている。

上記のマウスクリックはpage.click(<selector>)を使って下記のように書ける。

let selector = 'input[type="button"]';
await page.waitForSelector(selector);
await page.click(selector);

いずれにせよ、ブラウザ操作は下記の繰り返しになる。

  • domを待つ
  • domを指定してJavaScriptを実行する

JavaScriptから値の取得

JavaScriptを実行した関数のreturnで、JavaScriptから値を返すことができる。

dominnerTextは下記のようにして取得できる。

let selector = 'div';
await page.waitForSelector(selector);
const text = await page.$eval(selector, dom=> dom.innerText);
console.log(text);

JavaScriptへを渡す

page.$eval()の第3引数に値を渡すと、第2引数の関数の第2引数となって、値をJavaScriptに渡すことができる。

inputvalueは下記のようにしてセットできる。

const userName = 'ABC';
let selector = 'input[name="user"]';
await page.waitForSelector(selector);
await page.$eval(selector, (dom, val)=>{ dom.value = val }, userName);

複数要素

セレクターが複数domにマッチする場合がある。

page.$eval()はそのうち最初にマッチしたdomのみがJavaScriptに渡るが、page.$$eval()を使うと、マッチするdomの配列がJavaScriptに渡る。

optionvalueを配列で取得する

let selector = 'select option';
await page.waitForSelector(selector);
const res = await page.$$eval(selector, doms=>{
    const optionVals = [];
    for(const dom of doms){
        res.push(dom.innerText);
    }
    return optionVals;
});
console.log(res);

要素

操作

  • page.click(<selector>)
  • page.type(<selector>, <value>)
    • 文字列打ち込み
  • page.focus(<selector>)
  • page.$eval(<selector>,(dom, val)=>{ dom.value = val }, <val>)
    • <input>valueをセット

その他、domを操作したい時は、$eval()を使ってJavaScriptで直接操作する。

属性

  • page.$eval(<selector>, dom=> dom.getAttribute(<attribute_name>))

その他、domから情報を取得したい時は、$eval()を使ってJavaScriptで直接取得する。

ナビゲーション

遷移

  • page.goto(<url>)
  • page.reload()

ページロード完了を待つ

  • page.waitForNavigation()
  • page.waitForNetworkIdle()

属性

  • page.title()
  • page.url()
  • page.content()
    • ページのhtml

感想など

他にもファイルのアップロード・ダウンロードや、target="_blank"での新しいページ取得など、クローリングでよくあるケースもまとめようかと思っていました。

しかし、puppeteerはそういった事に対して都度機能を提供していくのではなく、ユーザーが自分でJavaScriptを書いて実装するというスタンスなので、puppeteerの使い方というよりJavaScriptの話になってしまうので今回は割愛しました。

SeleniumやPlaywrightは、要素を取得してその要素のメソッドを使って操作するという書き方なのですが、puppeteerはChrome DevTools Protocolの呼び出しをライブラリ化したものなので、ページのメソッドを使って、対象要素を引数で指定して操作するという書き方になります。

puppeteerは何かやろうとすると無骨なコードになることが多いのですが、それは、SeleniumやPlaywrightはブラウザ作業の自動化が目的のライブラリなのに対し、puppeteerはブラウザとの通信が目的のライブラリと目的の違いに起因しています。

関連カテゴリー記事

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com