Jupyter NotebookでPlaywrightを利用する

前回PlaywrightをJupyter Notebook上で操作していましたが、注意点等を補足として残しておきます。

環境

  • VSCode: 1.82.2
  • Docker Desktop: 4.18.0
  • Debian bullseye
  • Python: 3.11.3
  • Jupyter Notebook: 1.0.0
  • Playwright: 1.38.0

Playwrightのインストール

下記のようにインストールを行います。 これもセルで実行したい場合は、各コマンドの先頭に!を付加します。

pip install playwright
playwright install
playwright install-deps

Playwrightを利用してコードを作成する

Jupyter NotebookのセルでPlaywrightを使いたい場合、非同期処理で実装する必要があります。 具体的にはPlaywrightの非同期APIplaywright.async_apiを利用し、各メソッドの呼び出しにはawaitを付加する必要があります。 また、これらのコードを含む関数にもasyncをつけて非同期実行の関数として宣言する必要があります。

import asyncio
from playwright.async_api import async_playwright

async with async_playwright() as p:
    browser = await p.chromium.launch()
    context = await browser.new_context()
    page = await context.new_page()

    await page.goto("https://example.com")
    await page.wait_for_load_state("networkidle")
    content = await page.content()
    print(content)

    await context.close()
    await browser.close()

非同期処理ではない書き方だとRuntimeErrorが発生します。

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In [4], line 20
     17         # ブラウザを閉じる
     18         await browser.close()
---> 20 asyncio.run(main())

File /usr/lib/python3.10/asyncio/runners.py:33, in run(main, debug)
      9 """Execute the coroutine and return the result.
     10 
     11 This function runs the passed coroutine, taking care of
   (...)
     30     asyncio.run(main())
     31 """
     32 if events._get_running_loop() is not None:
---> 33     raise RuntimeError(
     34         "asyncio.run() cannot be called from a running event loop")
     36 if not coroutines.iscoroutine(main):
     37     raise ValueError("a coroutine was expected, got {!r}".format(main))

RuntimeError: asyncio.run() cannot be called from a running event loop

実行結果

example.comにアクセスする例です。 以下のようにWebページを取得できます。

<!DOCTYPE html><html><head>
    <title>Example Domain</title>

    <meta charset="utf-8">
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
        
    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>


</body></html>