docker, playwright, python環境でスクレイピングとローカルストレージ


GUI環境がないサーバーでweb scrapingをしようとして以下の問題にぶち当たった。
1. ページの表示内容をページ内で設定できる。が、GUIはない。
2. docker containerでplaywright/pythonを使っているのでブラウザの設定が毎回消える

2については、ホスト側のディレクトリをコンテナで/appにマウントして、そこにブラウザのローカルストレージを確保するようにした。
1については、WindowsのChromeでスクレイピングしたいページを開いて、開発者ツールでローカルストレージの内容をみつつ、ページの設定変更して設定項目と内容をチェックして、ヘッドレスブラウザ上でjavascriptで設定するようにした。

dockerでホスト側のディレクトリをマウントするには以下の引数で。
 -v LOCALSTORAGE_DIR:/app

設定項目と値を記録しておき、以下のコードに設定項目と値を書き込んで実行したらよい。

import asyncio
from playwright.async_api import async_playwright
import json

SITE_URL = 'YOUR_SITE_URL'
BROWSER_DATA_DIR = '/app/browser_data'

async def run():
    async with async_playwright() as p:
        context = await p.chromium.launch_persistent_context(
            headless=True,                    # ヘッドレスブラウザ指定
        )

        page = await context.new_page()

        # URLを開きます
        print(f"goto url=[{SITE_URL}]")
        response = await page.goto(SITE_URL)

        # HTTPステータスコードを確認
        if response.status == 200:
            print("Page loaded successfully!")
        else:
            print(f"Failed to load page, status code: {response.status}, status text: {response.status_text}")


        await page.wait_for_load_state("load")

        #3秒じゃダメだったんで30秒待つことにする
        await page.wait_for_selector("table#planesTable", timeout=30000)

        #ローカルストレージからデータを読み込む
        localStorageData = await page.evaluate("() => { return JSON.stringify(localStorage);}")
        print( json.dumps(json.loads(localStorageData), indent=4) )

        # ローカルストレージにデータを書き込む
        await page.evaluate("() => { localStorage.setItem('ITEM_1',        'true' ); }")
        await page.evaluate("() => { localStorage.setItem('ITEM_2',        '650'  ); }")

        print("ローカルストレージに、各種パラメータをセット")

        #ローカルストレージからデータを読み込む
        localStorageData = await page.evaluate("() => { return JSON.stringify(localStorage);}")
        print( json.dumps(json.loads(localStorageData), indent=4) )

        await context.close()  # ブラウザを閉じる

# 非同期関数を実行
asyncio.run(run())