LoginSignup
9
7

More than 3 years have passed since last update.

pyppeteer製のクローラをplaywright-pythonに移行したときのTips

Last updated at Posted at 2021-02-28

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で書かなくても良い(もちろん書いても良い)ので、よりとっつきやすくなっています。

pyppeteer.py
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())
playwright.py
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に食わせるタイプとして実装されていれば、特に変更不要です。

python
page = context.new_page()
page.goto(url)

html = page.content()

■Dockernize

公式の https://github.com/microsoft/playwright-python/blob/master/Dockerfile を参考にしてください。

ライブラリが足りない場合、実行時に丁寧に表示されるので、とりあえず流してみて、エラーがあれば追加してあげるのが良さそうです。

shell

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用)

Dockerfile
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"を突っ込んでください。環境変数に設定してあげてもよいかと思います。

■移行で注意すべき点

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、おすすめです!


  1. 各バイナリが200MBくらいあるので 

9
7
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
9
7