pyppeteer-チュートリアル

2022/08/09に公開

pyppeteer とは、 puppeteer (パッペッティア: 人形遣い) と呼ばれるGoogle製のJavaScriptのパッケージを、Pythonに移植[1]したものです。

PuppeteerChromium をヘッドレスモードでプログラムが操作することを目的としたパッケージで、 Puppeteer または、 Pyppeteer を使うことで以下のようなことができます。

  • WebPageを表示する
  • フォーム送信の自動化
  • ブラウザ操作の自動化
  • 自動化テスト
  • 画面のスクリーンショットやPDFの生成
  • シングルページアプリケーションのテスト

ブラウザで手動でできることのほとんどのことは、Puppeteerを使えばできるようになります。
urllibrequests (requests-htmlではない) ではJavaScriptを使用して生成される SPA (シングルページアプリケーション) などからデータを取得することをできません。
ですが、Puppeteer および Pyppeteer を利用すればJavaScriptで更新されるようなページのデータの取得も可能になります。

JavaScriptの場合

JavaScriptを利用してPuppeteerでデータを収集する場合は、
ChromeにてF12コマンドを押下して「Recorder」タブを開いて自動でスクリプトファイルを作成できます。

環境作成

Pythonのインストールが完了していることを前提としています。
まだ環境構築が完了してない場合は、Pythonの仮想環境構築を参考に環境を構築してください。

bash - 仮想環境作成
mkdir -p pyppeteer-sample/log
cd pyppeteer-sample
# 環境作成 -> 有効化
python -m venv venv # 環境作成
. venv/bin/activate # 環境有効化
pip install pyppeteer # インストール
環境が不要になった場合の後処理

有効化した環境を無効化する場合は以下のコマンドを実行してください。

bash - 仮想環境無効化
deactivate # 無効化

環境をもう利用しない場合は、rm -rf pyppeteer-sampleにてフォルダごと削除してください。

最も簡単な利用例

pyppeteerは、他のブラウザテストフレームワークを使用している人には馴染み深いものでしょう。Browserのインスタンスを作成し、ページを開き、PuppeteerのAPIで操作するのです。

例 - https://google.comに移動し、スクリーンショットを google.png という名前で保存する。

sample1.py
import asyncio
from pyppeteer import launch
from pyppeteer.browser import Browser
from pyppeteer.page import Page

async def main():
    browser: Browser = await launch(headless=False)
    page: Page = await browser.newPage()
    await page.goto("https://google.com")
    await page.screenshot({"path": "./log/google.png"})
    await browser.close()

if __name__ == "__main__":
    asyncio.new_event_loop().run_until_complete(main())

コマンドラインからスクリプトを実行する。

bash - sample1.pyを実行
python sample1.py
はじめて pyppeter を実行した場合

はじめてpyppeterを実行したときはホームディレクトリ下に、Chromiumがダウンロードされます。

初回起動時
(venv) mook@pc:python3.10$ python sample1.py
[INFO] Starting Chromium download.
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 109M/109M [00:21<00:00, 5.10Mb/s]
[INFO] Beginning extraction
[INFO] Chromium extracted to: /home/mook/.local/share/pyppeteer/local-chromium/588429

実行するとChromeが表示され、Googleのページが表示されればOKです。
また、logフォルダ配下に画面コピーが保存されます。

画面サイズを変更する

Pyppeteer は、初期ページサイズを 800×400px に設定します。ページサイズは、Page.setViewport()でカスタマイズすることができます。

sample1.py - 画面サイズを変更
async def main():
    args = ["--start-maximized"] # Windows最大化
    browser: Browser = await launch(
        headless=False,
        args=args, 
    )
    page: Page = await browser.newPage()
    await page.setViewport({"width": 800, "height": 1000})
    await page.goto("https://google.com")
    await page.screenshot(path="./log/google.png", fullpage=True)
    await browser.close()

ページをPDFとして保存

次は、ページ遷移後にPDFを作成し、 sample2.pdf という名前で保存します。
headlessモードでないとエラーが発生しPDF化できません。

sample2.py
import asyncio
from pyppeteer import launch
from pyppeteer.browser import Browser
from pyppeteer.page import Page

async def main():
    args = ["--start-maximized"]
    browser: Browser = await launch(args=args)
    page: Page = await browser.newPage()
    await page.goto("https://google.com")
    await page.pdf({"path": "./log/google.pdf", "format": "a4"})
    await browser.close()

if __name__ == "__main__":
    asyncio.new_event_loop().run_until_complete(main())

コマンドラインからスクリプトを実行する。

bash - sample2.pyを実行
python sample2.py

コンテキストでスクリプトを評価する(JavaScriptの実行)

ページからJavaScript実行し、実行結果を取得する。
JavaScriptによるページの操作を可能にします。

sample3.py
import asyncio
from pyppeteer import launch
from pyppeteer.browser import Browser
from pyppeteer.page import Page

async def main():
    args = ["--start-maximized"]
    browser: Browser = await launch(args=args)
    page: Page = await browser.newPage()
    await page.setViewport({"width": 800, "height": 1000})
    await page.goto("https://google.com")

    dimensions = await page.evaluate(
        """() => {
        return {
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight,
            deviceScaleFactor: window.devicePixelRatio,
        }
    }"""
    )
    print(dimensions)
    await browser.close()

if __name__ == "__main__":
    asyncio.new_event_loop().run_until_complete(main())

コマンドラインからスクリプトを実行する。

bash - sample3.pyを実行
python sample3.py
# {'width': 800, 'height': 1000, 'deviceScaleFactor': 1}

evaluateや、evaluateOnNewDocumentexopseFunctionなどの関連するメソッドは、Page.evaluate()を参照してください。

デフォルトの設定

  1. ヘッドレスモードを使用します

PyppeteerChromiumヘッドレスモード(画面を表示しないモード) で起動します。Chromium を フルバージョンで起動するには、ブラウザを起動する際に、ヘッドレスオプションを設定します。(headlessは画面を表示しないモード)

browser: Browser = await launch(headless=False)
  1. 新しいユーザープロファイルを作成する。
    Pyppeteerは独自のブラウザ・ユーザプロファイル(パスワードを入力した時に、Chromeからパスワード保存するか確認されるがそれらの情報を保存しているところ)を作成し、実行のたびにクリーンアップします。

便利なオプション

slowMo はブラウザの動作を指定 ms 分遅くします。

browser: Browser = await launch(
  headless = False,
  slowMo = 250 # 250ms ブラウザ動作を遅くする
);

Pyppeteer と Puppeteer の相違点

PyppeteerはPuppeteerのAPIをできる限り再現するように設計されていますが、JavaScriptPython という違いにより、これを正確に行うことは困難です。具体的な情報に知りたい場合は、こちらを参照してください。

メソッド等の引数について

Puppeteerは、関数/メソッドにオプションを渡すためにオブジェクトを使用します。
Pyppeteerのメソッド/関数は、オプションに辞書とキーワード引数の両方を受け付けます。

辞書を利用してオプションを指定する

browser = await launch({'headless': True})

keyword 引数を利用してオプションを指定する

browser = await launch(headless=True)

上記の2つは同じ結果を得ることが可能です。違いは引数の渡し方だけです。

要素セレクタのメソッド名

Pythonでは、は有効な識別子ではありません。Puppeteerの ` 、 `x` メソッドに相当するメソッドは以下のようになります。

puppeteer pyppeteer pyppeteer shorthand
Page.$() Page.querySelector() Page.J()
Page.$$() Page.querySelectorAll() Page.JJ()
Page.$x() Page.xpath() Page.Jx()

Page.evaluate() および Page.querySelectorEval() の引数

pyppeteerは、JavaScriptの式や関数の文字列表現を受け取ります。pyppeteerは、文字列が関数化指揮下自動的に検出しようとしますが、時々失敗します。もし式が誤って関数として扱われ、エラーが発生した場合は、force_exprをTrueに設定し、 pyppeteer に文字列を式として扱わせるようにしてみてください。

脚注
  1. Puppeteer (Chrome の自動操作ライブラリ) を Python に移植してpyppeteerという名前で公開しました ↩︎

Discussion