Open7

Playwright調査

to_obarato_obara

今まではSeleniumを使ってきていて、特に不満もなく暮らしていたが、Playwrightというものを知り、これは調べてみねばということでR。
特に個人的な課題認識として、とりあえずsleepしておこうぜ的なことをなんとかしたいという感じです。

to_obarato_obara
$ sw_vers                                                                                                                                                       ✘ 130
ProductName:    macOS
ProductVersion: 11.2.1
BuildVersion:   20D74
$ pyenv --version
pyenv 1.2.23
$ LDFLAGS="-L$(xcrun --show-sdk-path)/usr/lib" pyenv install 3.9.0
$ pyenv local 3.9.0
$ pip install --upgrade pip
$ pip install playwright
$ pip list playwright
Package           Version
----------------- -------
greenlet          1.0.0
pip               21.0.1
playwright        1.9.1
pyee              8.1.0
setuptools        49.2.1
typing-extensions 3.7.4.3

to_obarato_obara

urlの操作を自動生成

$ playwright codegen url -o test.py

nameとかtextで識別する傾向にあるのは気になるところだけど、まぁ、便利です。

to_obarato_obara

テンプレート的には以下のようなコードが出力される


from playwright.sync_api import sync_playwright

def run(playwright):
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()

    # Open new page
    page = context.new_page()

    # Go to url
    page.goto("url")

with sync_playwright() as playwright:
  run(playwright)

to_obarato_obara

ちなみに、以下のようなコードだと、エラーが出ます。

from playwright.sync_api import sync_playwright

if __name__ == '__main__':

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
    context = browser.new_context()

RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'Browser.new_context' was never awaited

イベント待ちのループが無いため。うまくクラスとかでラッピングする場合には、以下のようにすると良さそうです。

from playwright.sync_api import sync_playwright

class crawler:

    @staticmethod
    def factory():
        playwright = sync_playwright().start()
        return crawler(playwright)
    def __init__(self, playwright):
        self.playwright = playwright
    def __del__(self):
        self.page.close()
        self.context.close()
        self.browser.close()

        self.playwright.stop()

if __name__ == '__main__':
    cr = crawler.factory()
    cr.xxx()
to_obarato_obara

ドロップダウンリストをOptionで指定された値で選択しようとした。
codegenを利用して試してみると、以下のようなコードが吐かれた。
page1.selectOption("select[id="id"]", "value")
で、実際に組み込んで試してみると、以下のようなエラーが。。。

AttributeError: 'Page' object has no attribute 'selectOption'

うぬぬ、ということで、マニュアルをあたってみると、名称が変わっているっぽいです。。
page1.select_option("select[id="id"]", "value")
こちらが正解