SPA向けのクローラをpyppeteerで実装していたのですが、playwright-pythonに移行してみました。
基本的な使い心地はそのままに、細かいところで便利になっている印象なので、pyppeteerを単純なクローラとして利用しているのでしたら、試してみてはいかがでしょうか。
■導入
普通にpip, pipenv, poetry等でplaywright-pythonを入れたあと、playwright install
もしくはpython -m playwright install
で各ブラウザのバイナリを取得します。
$ poetry add playwright
$ poetry run playwright install
ただし、これだとchromium
/firefox
/webkit
の全バイナリが入ってしまうので、クローラのように複数ブラウザで動かす必要がない場合は、利用するブラウザを明示的に指定するのがおすすめです。1
$ poetry run playwright install webkit
■スクリプトの書き換え
pyppeteerとほとんど変わりませんが、asyncで書かなくても良い(もちろん書いても良い)ので、よりとっつきやすくなっています。
import asyncio
from pyppeteer import launch
async def main():
browser = await launch({
"args": ["--no-sandbox"],
"slowMo": 5,
"headless": True,
})
page = await browser.newPage()
await page.goto('https://example.com')
await page.screenshot({'path': 'example.png'})
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
iphone_11 = p.devices["iPhone 11 Pro"]
browser = p.webkit.launch(headless=True)
context = browser.new_context(**iphone_11)
page = context.new_page()
page.goto("https://example.com")
page.screenshot(path="example.png")
browser.close()
- 参考:
page.waitFor()
やslowMo
が不要に
Auto-waitingが優秀で、画面描画に合わせてpage.waitFor()
やslowMo
で適宜waitを入れてやらなくても、いい感じに処理してくれます。
余計なwaitがないと実行時間も短くなるので、とりあえず消して試してみるのがおすすめです。
device
viewportとかその辺の設定がdeviceとしてビルトインで提供されていて楽ちんです。対応デバイス一覧は以下を参照。
任意のデバイスを定義して使う場合はこんな感じ。
browser = playwright.webkit.launch(headless=True)
device = {
'user_agent': 'foobar',
'viewport': {
'width': 1200,
'height': 2048
},
'device_scale_factor': 1,
'is_mobile': True,
'has_touch': True,
'default_browser_type': 'webkit'
}
context = browser.new_context(**device)
クローラとしてUAを明示したいだけなら、以下でOKです。
browser = playwright.webkit.launch(headless=True)
context = browser.new_context(user_agent="foobar")
HTML文字列取得
pyppeteerと同じなので、クローラがhtml文字列をlxmlやbs4に食わせるタイプとして実装されていれば、特に変更不要です。
page = context.new_page()
page.goto(url)
html = page.content()
■Dockernize
公式の https://github.com/microsoft/playwright-python/blob/master/Dockerfile を参考にしてください。
ライブラリが足りない場合、実行時に丁寧に表示されるので、とりあえず流してみて、エラーがあれば追加してあげるのが良さそうです。
playwright._impl._api_types.Error: Host system is missing dependencies!
Install missing packages with:
sudo apt-get install libnss3\
libnspr4\
libasound2
参考に、以下に動作確認したものを示します。(2021/02/28: webkit用)
FROM ubuntu:focal
# 0. Browser-binaries path (site-packages/playwright)
# @see https://playwright.dev/python/docs/installation/#managing-browser-binaries
ENV PLAYWRIGHT_BROWSERS_PATH 0
# 1. Install latest Python
RUN apt-get update && apt-get install -y python3 python3-pip && \
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 && \
update-alternatives --install /usr/bin/python python /usr/bin/python3 1
# 2. Install WebKit dependencies
RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
libwoff1 \
libopus0 \
libwebp6 \
libwebpdemux2 \
libenchant1c2a \
libgudev-1.0-0 \
libsecret-1-0 \
libhyphen0 \
libgdk-pixbuf2.0-0 \
libegl1 \
libnotify4 \
libxslt1.1 \
libevent-2.1-7 \
libgles2 \
libxcomposite1 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libepoxy0 \
libgtk-3-0 \
libharfbuzz-icu0
# 3. Install gstreamer and plugins to support video playback in WebKit.
RUN apt-get update && apt-get install -y --no-install-recommends \
libgstreamer-gl1.0-0 \
libgstreamer-plugins-bad1.0-0 \
gstreamer1.0-plugins-good \
gstreamer1.0-libav \
# add
libvpx6\
libgstreamer-plugins-base1.0-0\
libgstreamer1.0-0\
libopenjp2-7
RUN apt-get update \
&& pip install --upgrade pip \
&& pip install --no-cache-dir poetry && poetry config virtualenvs.create false && poetry install --no-dev \
&& python -m playwright install webkit \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
なお、GitHub Actions経由で実行した場合など、コンテナの実行環境によっては予期していないbrowser binariesパスを見に行ってしまうことがあります。
これを防ぐには、以下のように対応してください。
- 環境変数に
PLAYWRIGHT_BROWSERS_PATH=0
と指定-
site-packages/playwright
以下がbrowser binariesパスになる- (上記サンプルはこれ、具体的には
/usr/local/lib/python3.8/dist-packages/playwright/driver/package/.local-browsers/
になりました)
- (上記サンプルはこれ、具体的には
-
- 環境変数に
PLAYWRIGHT_BROWSERS_PATH
を明示的に指定-
PLAYWRIGHT_BROWSERS_PATH=/root/.cache/ms-playwright
とか
-
参照: https://playwright.dev/python/docs/installation/#managing-browser-binaries
なお、pyppeteerでDockerコンテナ経由の実行時に必要だった"args": ["--no-sandbox"]
は、playwrightでは不要になります。
(備考) tz選択が出て止まってしまう場合
Configuring tzdata
------------------
Please select the geographic area in which you live. Subsequent configuration
questions will narrow this down by presenting a list of cities, representing
the time zones in which they are located.
1. Africa 4. Australia 7. Atlantic 10. Pacific 13. Etc
2. America 5. Arctic 8. Europe 11. SystemV
3. Antarctica 6. Asia 9. Indian 12. US
Geographic area:
DEBIAN_FRONTEND="noninteractive"
を突っ込んでください。環境変数に設定してあげてもよいかと思います。
- 参考
- Docker Ubuntu18.04でtzdataをinstallするときにtimezoneの選択をしないでinstallする - Qiita https://qiita.com/yagince/items/deba267f789604643bab
■移行で注意すべき点
pyppeteerで使われているChromiumのバージョンはかなり古い
pyppeteerで使われているChromiumのバージョンはかなり古い(REV:588429)です。
playwright-python(2021/02/28時点)だとREV:854489なので、そのあたりに起因する挙動の違いがないとも限りません。注意してください。
playwright-python公式のベースイメージはUbuntu Focal Fossa(20.04)
DockerHubのpythonイメージとかconda系を使ってる場合、playwrightに必要なライブラリがなくて困ったりするかもしれません。
私はpython:3.8.6-slim
を使ってたんですがlibevent-2.1-7
が見当たらなくてうーん…ってなりました。
頑張る気力がなかったので、playwrightに寄せる形でクローラのベースイメージをubuntu:focal
にしてしまいましたが、クローラで使っている他のライブラリの依存関係が厳しめな場合、注意が必要です。
ちなみにubuntu:focal
のpython3は3.8.5
だったので、その辺も現在お使いのライブラリによっては、調整が必要になるかもしれません。
■最後に
「pyppeteerのスペルに気を使わなくて良くなる」、この一点だけでもplaywright-python、おすすめです!
-
各バイナリが200MBくらいあるので ↩