PlaywrightとScrapelessを使ってlocalStorageをスクレイピングする方法
Expert in Web Scraping Technologies
ブラウザはDOMの外で有用なページの状態を保持できます。このガイドでは、Playwrightを使用して、公開されているMDNデモでlocalStorageを検査し、UIを通じて3つの実際の設定を変更し、別のタブで結果のストレージイベントをキャプチャし、リロード後も値が生き残ることを証明し、その同じロジックをScrapeless Scraping Browserに移動します。
スクレイピングワークフローにおけるWebストレージの追加
WebストレージAPIは、オリジンに2つの文字列キーのストアを提供します:
localStorageは同一オリジンのドキュメントで共有され、普通のページリロードやブラウザの再起動を生き残ります(プロファイルが永続的な場合)。sessionStorageは1つの最上位のブラウジングコンテキストに制限され、そのページセッションの間のみ持続します。
どちらのストアもクッキーの入れ物ではありません。Webストレージの値は自動的にHTTPリクエストに添付されることはなく、すべてのキー/値は文字列です。MDNのWebストレージAPIガイドではこれらのスコープと持続性の境界を定義しています。
スクレイピングにおいて、ストレージにはUIの好み、キャッシュされた識別子、機能の状態、またはアプリケーションがすでに読み込んだ公開データが含まれる可能性があります。それを検証するためのブラウザの状態と見なし、認証トークンやプライベートなユーザーデータを収集する理由としては扱わないでください。
ScrapelessとのPlaywrightの使用理由
PlaywrightはページのオリジンでJavaScriptを評価でき、同じBrowserContext内に2つのページを開き、ブラウザ自身のストレージイベントを観察できます。Scrapeless Scraping Browserは、Playwright APIを保持しつつ、ホスティングされたChromiumセッションを提供します。
ブラウザ接続はconnect_over_cdpを使用します。pageが存在する場合、ストレージの検査はChromiumがローカルかホスティングされているかに関わらず同じです。
前提条件
- Python 3.10以降。
playwright1.59.0または現在の互換バージョン。- 完全な実行可能な例のためのローカルChrome/Chromium。
- クラウド接続のための資金提供されたScrapelessアカウントおよび
SCRAPELESS_API_KEY。検証アカウントの新しいブラウザセッションはコード14500を返したため、接続ブロックは明示的な前提条件のギャップです。
インストール
bash
python -m pip install "playwright==1.59.0"
Scrapeless Scraping Browserに接続
注: このブロックは資金提供されたScraping Browserの残高が必要です。最終的な検証アカウントは
insufficient balance, please recharge firstを返しました。自分の資金提供されたキーで実行してください; 以下の完全なストレージワークフローは同じ公開ページに対してローカルChromeで実行されました。
python
import os
from urllib.parse import urlencode
from playwright.sync_api import sync_playwright
params = urlencode({
"token": os.environ["SCRAPELESS_API_KEY"],
"sessionTTL": 120,
"proxyCountry": "US",
})
cdp_url = f"wss://browser.scrapeless.com/api/v2/browser?{params}"
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
context = browser.contexts[0]
page = context.pages[0]
# ここでコンテキストとページを使ってストレージステップを実行します。
browser.close()
現在の接続パラメータについてはScrapeless開発者ドキュメントを参照してください。
すべてのlocalStorageキーを検査
MDNの公開デモは、背景色、フォント、画像の選択を保存します:
python
TARGET_URL = "https://mdn.github.io/dom-examples/web-storage/"
page.goto(TARGET_URL, wait_until="domcontentloaded")
stored = page.evaluate(
"Object.fromEntries(Object.entries(localStorage))"
)
print("初期ストレージ:", stored)
print("セッションストレージ:", page.evaluate("sessionStorage.length"))
text
初期ストレージ: {'font': 'sans-serif', 'image': 'images/firefoxos.png', 'bgcolor': 'FF0000'}
セッションストレージ: 0
すべてのエントリを読み込むことで、エクストラクターを1つのキーに結び付けずに済みます。出力にオリジンを保持してください。同じキー名が別のサイトでは異なる意味を持つ可能性があります。
変更を別のタブでキャプチャ
storageイベントは、変更されたストアを共有する他の同一オリジンのドキュメントで発生します。変更を行ったタブでは発生しません。
python
observer_page = context.new_page()
observer_page.goto(TARGET_URL, wait_until="domcontentloaded")
observer_page.evaluate("""
window.capturedStorageEvents = [];
addEventListener('storage', event => {
capturedStorageEvents.push({
key: event.key,
oldValue: event.oldValue,
newValue: event.newValue,
});
});
""")
両方のページは1つのブラウザコンテキストとオリジンを共有する必要があります。別のコンテキストは別々のストレージを持ち、これらのイベントを受け取ることはありません。
実際のUIコントロールを変更する
デモのコントロールを直接キーを書き込むのではなく変更する:
python
page.evaluate("""
bgcolor.value = '00FF00';
bgcolor.dispatchEvent(new Event('change', {bubbles: true}));
""")
page.select_option("#font", "serif")
page.select_option("#image", "images/crocodile.png")
page.wait_for_timeout(500)
print("更新されたストレージ:", page.evaluate(
"Object.fromEntries(Object.entries(localStorage))"
))
print("イベント:", observer_page.evaluate("capturedStorageEvents"))
text
更新されたストレージ: {'font': 'serif', 'image': 'images/crocodile.png', 'bgcolor': '00FF00'}
イベント: [{'key': 'bgcolor', 'oldValue': 'FF0000', 'newValue': '00FF00'}, {'key': 'font', 'oldValue': 'sans-serif', 'newValue': 'serif'}, {'key': 'image', 'oldValue': 'images/firefoxos.png', 'newValue': 'images/crocodile.png'}]
その出力は3つのことを同時に証明します: UIがストレージを更新したこと、2番目のタブがちょうど3つの変更を受け取ったこと、そして各イベントがその前の値を保持したことです。
ホストセッションで状態を確認する準備はできましたか?無料のScrapelessアカウントを作成する して、ブラウザ作成のみを置き換えてください。
値がリロード後も生存することを証明する
python
page.reload(wait_until="domcontentloaded")
reloaded = page.evaluate(
"Object.fromEntries(Object.entries(localStorage))"
)
controls = {
"bgcolor": page.locator("#bgcolor").input_value(),
"font": page.locator("#font").input_value(),
"image": page.locator("#image").input_value(),
}
print("リロードされたストレージ:", reloaded)
print("コントロールの値:", controls)
text
リロードされたストレージ: {'font': 'serif', 'image': 'images/crocodile.png', 'bgcolor': '00FF00'}
コントロールの値: {'bgcolor': '00FF00', 'font': 'serif', 'image': 'images/crocodile.png'}
可視のコントロールと保存された状態が一致することは、ストレージだけを確認するよりも強力です。それは、アプリケーションがナビゲーション後に保存された値を消費したことを証明します。
完全な実行可能スクリプト
python
from playwright.sync_api import sync_playwright
TARGET_URL = "https://mdn.github.io/dom-examples/web-storage/"
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path="/usr/bin/google-chrome",
headless=True,
)
context = browser.new_context()
page = context.new_page()
observer_page = context.new_page()
observer_page.goto(TARGET_URL, wait_until="domcontentloaded")
observer_page.evaluate("""
window.capturedStorageEvents = [];
addEventListener('storage', event => {
capturedStorageEvents.push({
key: event.key,
oldValue: event.oldValue,
newValue: event.newValue,
});
});
""")
page.goto(TARGET_URL, wait_until="domcontentloaded")
initial = page.evaluate(
"Object.fromEntries(Object.entries(localStorage))"
)
page.evaluate("""
bgcolor.value = '00FF00';
bgcolor.dispatchEvent(new Event('change', {bubbles: true}));
""")
page.select_option("#font", "serif")
page.select_option("#image", "images/crocodile.png")
page.wait_for_timeout(500)
updated = page.evaluate(
"Object.fromEntries(Object.entries(localStorage))"
)
events = observer_page.evaluate("capturedStorageEvents")
page.reload(wait_until="domcontentloaded")
reloaded = page.evaluate(
"Object.fromEntries(Object.entries(localStorage))"
)
controls = {
"bgcolor": page.locator("#bgcolor").input_value(),
"font": page.locator("#font").input_value(),
"image": page.locator("#image").input_value(),
}
assert len(events) == 3
assert updated == reloaded == controls
assert page.evaluate("sessionStorage.length") == 0
print("タイトル:", page.title())
print("初期ストレージ:", initial)
print("更新されたストレージ:", updated)
print("イベントキー:", [event["key"] for event in events])
print("イベント数:", len(events))
print("リロードされたストレージ:", reloaded)
print("コントロールの値:", controls)
print("セッションストレージのエントリ:", page.evaluate("sessionStorage.length"))
browser.close()
この実行は、3つの初期キー、3つの更新されたキー、3つのタブ間イベント、一致するリロードされたコントロール、そしてゼロのセッションストレージエントリを返します。
localStorage、sessionStorage、及びクッキー
localStorage
同一オリジンの文書間で共有され、文字列のみで、クリアされるまで永続的。訪問間で状態を意図的に保持するアプリケーションに使用します。
sessionStorage
各トップレベルページセッションごとに独立。タブを複製または開くと、同じオリジンでも異なるライフサイクルが生じることがあります。その状態が重要なページから検査してください。
クッキー
クッキールールに従って、同じHTTP要求と共に送信されます。Webストレージと混同するのではなく、PlaywrightのコンテキストクッキーAPIを使用してください。
安全な抽出境界
ストレージには、認証情報、ユーザー識別子、またはプライベートな状態が含まれている可能性があります。例を公共デモページに制限し、特定のタスクに必要なフィールドのみを収集し、トークンやセッション素材を公開しないでください。ブラウザを通じたオリジンアクセスは、読み取れるすべての値を再利用する許可を与えるものではありません。
結論
Webストレージの抽出は、ブラウザに状態がある場合に役立ちますが、可視のDOMだけでは説明できません。完全なマップを読み取り、レコードとともにオリジンを保持し、由来が必要な場合にはクロスタブの変化を観察し、アプリケーションがナビゲーション後に保存された値を消費することを確認してください。ワークフローをScrapelessに移動すると、ブラウザ接続は変更されますが、ストレージロジックは変更されません。
Scrapelessを始める、Scrapelessの料金を確認する、およびCDPが公開するものを読む前に、状態を持つセッションをクラウドに移動してください。
FAQ
Q: PlaywrightはlocalStorageを読み取れますか?
はい。ターゲットオリジン内のページでObject.fromEntries(Object.entries(localStorage))を評価してください。
Q: すべてにcontext.storage_state()を使用しないのはなぜですか?
ストレージ状態はサポートされている認証状態をエクスポートするのに便利ですが、ページの直接評価により、ライブキーのマップを検査し、UIの変化やストレージイベントと相関させることができます。
Q: localStorageはリロードに耐えますか?
はい、アプリケーションまたはブラウザがそれをクリアしない限り。MDNデモの3つの変更された値は、テストされたリロードを生き残り、コントロールを再ポピュレートしました。
Q: localStorageを変更したタブはストレージイベントを受け取りますか?
いいえ。イベントはストアを共有する他の同一オリジンの文書に届けられるため、例では2ページ目でリスンしています。
Q: sessionStorageはタブ間で共有されますか?
いいえ。トップレベルのブラウジングコンテキストおよびその同一オリジンの子コンテキストにスコープされているので、特定のページセッションから検査してください。
Q: Webストレージの値は常にJSONですか?
いいえ。すべての値は文字列として保存されます。アプリケーションのフォーマットが確認された場合にのみJSONを解析し、無効なJSONを明示的に処理してください。
Q: ブラウザストレージをスクレイピングするのは安全ですか?
ターゲットの権限とあなたのデータ処理義務内でのみ安全です。認証情報やプライベートなユーザー状態を避け、収集を制限し、適用可能なサイトの利用規約とロボットポリシーを確認してください。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



