Blank File

LinuxとかPythonとかVimとか、趣味でいじる感じで

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

Puppeteer というJavaScriptchromeを自動操作するライブラリが最近話題になっていました。 私もPythonSeleniumの代わりに使えるものがほしかったので、puppeteerをPythonに移植し、pyppeteerという名前で公開しました。

Puppeteerについては下記Qiitaの投稿が参考になるかと思います。

使用上の注意

まだ作ったばかり&テスト不十分なのでバグがあると思います。 なので試す時は「うまく動いたらラッキー」くらいの人柱精神でお願いします。 特にwindowsでは全くテストしていないので動かないかもしれません。

一応自分でwdomテストに使ってみましたが、Webページのテストに使う分には意外と大丈夫です。 スクレイピング用途で使うとまだバグがあると思います。

バグに気づきましたらGitHubのIssueに報告していただけると幸いです。

修正してPR送っていただくのも大歓迎です。 その際はdevブランチのコードを修正する形でお願いします。

インストール

Python3.6以上のみの対応です。 pipでインストールできます。

python3 -m pip install pyppeteer

使い方

基本的にpuppeteerと同じです。 puppeteerのREADMEにあるWebページを開いてスクリーンショット画像を取得する例はPyppeteerでは以下のようになります。

import asyncio
from pyppeteer.launcher import launch

async def main(browser):
    page = await browser.newPage()
    await page.goto('http://example.com')
    await page.screenshot({'path': 'example.png'})

browser = launch()
asyncio.get_event_loop().run_until_complete(main(browser))
browser.close()

(2017/09/07 サンプルコード間違ってたので修正→再修正)

初回実行時だけは特定リビジョンのchrome (100MB程度) をダウンロードするので少し時間がかかります。 2回以降はすぐ終わると思います。


[2017/09/09: 追記]

下記不具合の対策をしました。 最新版(0.0.9)ではmacの場合unzipを使って展開します。 macで動かない方は最新版への更新をお願いします。

python3 -m pip install -U pyppeteer

[2017/09/08: 追記]

現在、OSXで実行するとダウンロードしたchromeの展開に失敗するようです。 展開が終わっているのにフリーズしたような状態になっている場合、お手数ですが手動でchromiumのダウンロードと展開・設置をお願いします。

これで再度実行してみてください。 それでも動かない場合はIssueに報告していただけるとありがたいです。

[追記おわり]


上記コードを実行すると同じディレクトリにexample.pngというファイルができているはずです。

APIは以下のドキュメントに列挙してあります。

async/awaitを多用しているため、かなりの数の関数/メソッドがcoroutine関数になっているので注意してください。 これらはドキュメントで名前の先頭に coroutine とついています。

pyppeteerのドキュメントではオプションなどについてかなり省略してしまっていますが、 puppeteerと同じになっているので必要があればpuppeteerのドキュメントを確認してください。

また、pyppeteer自体のテストも使い方の参考になるかもしれません。

上記テストで多用している@syncというデコレータについては下記の記事を参照してください(宣伝)。

h-miyako.hatenablog.com

Puppeteerとの違い

極力puppeteerとの違いが少ないようにしていますが、言語がJavaScriptPythonで違う関係上多少の違いがあります。

オプションのキーワード引数

puppeteerではオプションを辞書で設定する作りになっていますが、pyppeteerでは辞書・キーワード引数のどちらでも受け付けます。つまりPyppeteerは以下の2つの書き方が可能で、どちらも同じように動作します。

Puppeteerのように辞書で渡す:

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

キーワード引数で渡す:

browser = launch(headless=True)

要素を取得するメソッド名の違い

PuppeteerではPage.$(selector)というメソッドで要素を取得できますが、Pythonでは$が変数名に使えないのでPage.querySelector(selector)という名前になります。 長いのでPage.J(selector)という省略名も用意しました。

この方法で取得した要素 (Element) も同じようにElement.$が使えないのでElement.querySelectorまたはElement.Jとなります。

同様に$$メソッドはquerySelectorAllまたはJJになります。

evaluate()の引数

Page/Elementevaluate(JSfunction)メソッドではブラウザ上で任意のJavaScriptの関数を実行し、結果を取得することができます。

PuppeteerではJavaScriptの関数を直接引数として渡せますが、pythonではJavaScriptの関数を直接定義できませんしPythonの関数を渡しても仕方ないので、文字列で関数を渡します。

要素のテキストを取得する例は以下のようになります。

element = await page.querySelector('h1')
title = await element.evaluate('(element) => element.textContent')

Element.evaluate()に渡される関数の第一引数にはその要素(上の例ではh1要素)が渡されます。 (実はthisでも同じ要素が参照できます)

今後

テスト追加などで安定させ、本家puppeteerの更新に追従していこうと考えています。 機能追加についてはPython特有の機能であれば追加しますが、基本的に独自の機能は追加しないでpuppeteerとの整合性を取っていこうと考えています。

なので「こういう機能追加して!」という要望には基本的にお応えできないと思います。 puppeteerにあってこっちにない機能があれば対応しますのでお知らせください。