Communitygithub.com

アカウントデータスクレイピング

ユーザーがログインしたWebサイトから注文履歴、取引、請求書などを抽出するために使用します。公式エクスポートがない場合や、既存のスクレイパーリポジトリが古い/壊れている/パスワードを要求する場合に有効です。

アカウントデータスクレイピング とは?

このスキルは、ユーザーが自分自身のアカウントデータを、公式エクスポート機能がない(または遅い)Webサイトから抽出するためのワークフローを提供します。Playwrightブラウザ上でユーザー自身がログインし、エージェントはサイトの内部API(XHR、GraphQL、サーバーレンダリングHTML)を発見・再生することでデータを取得します。パスワードや認証コードは一切扱わず、ブラウザのセッションCookieとリクエストヘッダーを利用します。対応プラットフォームはPlaywrightが動作する任意のWebサイトであり、Claude Code, Cursor, CodexなどのAIエージェントツール上で動作します。ワークフローは、出力ディレクトリのGit管理からの除外、ブラウザ操作(ログイン)、データソースの発見、ページ内バックグラウンドでのページネーション、ファイル保存、解析と検証から構成されます。取得したデータは生のJSON/HTMLファイルとしてローカルに保存され、個人情報を含むためGitにはコミットしません。

対応~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/harwal2000/skills/tree/HEAD/skills/scraping-account-data

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

アカウントデータのスクレイピング

概要

ユーザーがPlaywrightブラウザ上で自らログインします。あなたはサイトのページが使用するデータソースを発見し、それをページ内で再生(セッションCookie+実際のヘッダー)し、生のレスポンスをディスクに保存します。資格情報は決して扱いません。

使用するタイミング

  • 「<サービス>の履歴を取得して」「注文/旅行/予約をスクレイピングして」「このスクレイパーリポジトリを使って」
  • 古いスクレイパーリポジトリ(requests + パスワード/OTPログイン): GitHubでエンドポイント名とセレクタのみを読むために使用します。決して実行しないでください。ボットチェック(HTTP 202空ボディ、キャプチャ)によって壊れ、パスワードを要求します。

最初に公式エクスポートを確認してください。 Google Takeout、「データをダウンロード」、GDPR/DPDPリクエスト、公開API、メールの領収書。遅いエクスポートは数日かかります。ユーザーに最初にリクエストしてもらい、今すぐスクレイピングし、到着したらIDで相互確認してください。

ワークフロー

  1. 何かを書き込む前に出力ディレクトリをgitignoreしてください(data/<service>/ またはプロジェクトの同等のもの)。git check-ignore で確認してください。生データには住所、電話番号、GPSが含まれます。
  2. 移動、ログインをハンドオフします。 アカウントページを開き、ユーザーにブラウザウィンドウで電話番号/パスワード/OTPを入力し、完了したら返信するよう伝えてください。チャットでコードを要求しないでください。
  3. データソースを発見します(browser-snippets.md §1)。リスナーを設定してリロードし、分類します:
    • JSON XHR/fetch(最良)— リストエンドポイント、ページネーションの形状(next_url/カーソル、page_number、オフセット=最後のID、endOfList)、および詳細エンドポイント(1つのアイテムを開く)をメモします。
    • GraphQL — 1つの POST /graphql。完全なリクエストボディ(operationName、query または persisted-query hash、variables)を記録します。
    • サーバーレンダリングHTML — データは document レスポンスに含まれます。リストおよび詳細ページをページ内で取得し、DOMParser でパースします。後で再パースできるように生のHTMLも保存します。
    • 分割リスト — リストがフィルター(年ドロップダウン、日付範囲、アーカイブ済み/キャンセル済み/デジタルなどのタブ)で分割されている場合、すべてのフィルター値を読み、それぞれをページネーションします。
  4. 認証。 まず fetch(url, {credentials: 'include'}) を試します。401/403/空が返ってきた場合は、ライブリクエストから非ブラウザヘッダーをコピーします(§2)。コピーするだけで、値を推測しないでください。ヘッダー名のみをログに記録し、値は決して表示または保存しないでください。
  5. ページ内でバックグラウンドページネーション(§2): window.__x = {running, pages, error}、リクエスト間隔1.5秒、リトライ、短い評価でポーリングします。各レスポンス: ログインページ/キャプチャページの場合(URLにsignin/captchaが含まれる、または期待されるJSONの代わりにHTML)、error を設定して停止します。これらはしばしば200として返されます。
  6. 移動する前に保存します(§3)。goto/リロードは window をクリアします。絶対 filename パスで browser_evaluate を使用し、オブジェクトを返します(JSON.stringify は二重エンコードされます)。ファイルあたり約5MBは許容されます。それを超える場合はバッチごとに分割します。
  7. 署名付き/再生不可能なリクエスト(リクエスト署名ヘッダー、nonce ボディ、編集を拒否する永続化クエリ): 各詳細ページにアクセスし、受動的にレスポンスをキャプチャします(§4)。
  8. ビルド+検証(以下参照)データディレクトリ外のパーサースクリプトで行い、次にインサイトノートを作成します。既存のリポジトリレイアウトがあればそれに従います(例: tools/<service>/build_db.py、データの横にノート)。そうでなければ質問します。

読み取り専用。 ページがデータを表示するためにリクエストするものだけを再生します。GraphQL: 操作で判断します(query/Get*/List*)、決して mutation ではありません。決して並べ替え、キャンセル、評価、アーカイブ、削除しないでください。

検証 — すべて実行してください

チェック理由
ページネーションがエラーやログインリダイレクトではなく、カーソル/リストの終了によって終了したサイレントトランケーション
最後に「アプリで古い注文を見る」のようなテキストがないか確認Webビューは履歴を制限(Swiggy: 約11ヶ月)
サイトのカウントエンドポイントやヘッダーだけを信頼しないBlinkitのカウントは40と言ったが、リストには83あった
コンポーネントが行ごとの合計と一致する(アイテム+料金−割引=支払額)パーサーのずれを検出。サイトが古いレコードの明細を省略している場合は、そう言うこと。無理に合わせない
アイテム価格がアイテム合計と一致する単価とライン合計の混同
一意のID。完全な重複を除去エクスポートと領収書で二重リストされることがある
別のソース(エクスポート、領収書)でIDを相互確認カバレッジを証明
すべてのリスト/タブ/フィルターがカバーされたか(アーカイブ、キャンセル、他の年、サブサービス)「すべての注文」はしばしば複数のリストにまたがる

パースに関する注意

  • サーバー駆動UI API(snippets、widgets、widget_type、layout): ウィジェットを順に処理し、各ウィジェットの text フィールドを収集し、既知のラベルでマッピングします。1テキストウィジェットは多くの場合、次のウィジェットのラベルです。ラベル名をホワイトリストに登録するか、すべてのフィールドがずれます。
  • 金額はパイサ/セントの場合があります。「FREE」=0。先頭の「-」=割引。通貨記号とインド式カンマ区切りを削除します。通貨は別々に保持します。
  • タイムスタンプ: 購入 → ユーザーのタイムゾーン。旅行/移動 → レコードの現地時間。
  • 生ファイルに日付を付けて保存します(orders-raw-YYYY-MM-DD.json)。ビルド済みのSQLiteの隣に置きます。

Git

以下だけをコミットします: gitignore行、パーサースクリプト、README/インデックス行。生ファイルとSQLiteはローカルに保持します。明示的なパスをステージングします(ダーティツリーで決して git add -A しない)。求められたときにのみコミットします。

よくある間違い

  • 1つの長い同期的なevaluateループ — タイムアウトします。バックグラウンド化してポーリングします。
  • チャットに一括データを返してしまう — filename を返すこと。
  • スニペットリスナーをアタッチしたままにする — page.off で解除するか、繰り返し実行でハンドラがスタックします。
  • HTMLレンダリングサイトでxhr/fetchのみに絞って発見し、「データソースがない」と結論づけること。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

関連スキル