Communitygithub.com

harwal2000/skills

當用戶希望從他們登入的網站匯出個人資料(如訂單歷史、行程、預訂、交易記錄、觀看或聆聽歷史、帳單、報表、收藏項目),但網站未提供可用的匯出功能,或現有的爬蟲套件已過時、損壞或要求密碼時使用。

skills 是什麼?

這個 AI 助手技能專注於幫助用戶從需要登入的網站中提取個人資料,例如訂單歷史、行程、預訂、交易記錄等。當官方匯出功能(如 Google Takeout、GDPR 請求)不可用、過於緩慢,或現有爬蟲套件已過時、損壞且要求密碼時,此技能便派上用場。它通過在 Playwright 瀏覽器中讓用戶手動登入,然後在頁面內重放網站自身的數據請求來獲取資料,從不處理用戶憑證。支援的平台包括任何通過瀏覽器存取的網站,尤其適合那些使用 JSON XHR/fetch、GraphQL 或伺服器端渲染 HTML 的站點。工作流程從用戶登入後,由 AI 引導發現數據源、在背景分頁處理請求、保存原始回應,並最終驗證數據完整性。它還包含了詳細的驗證檢查清單,以防止數據被截斷、重複或計算錯誤,並確保所有過濾器(如年份、分頁、類別)都被涵蓋。

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/harwal2000/skills/tree/HEAD/skills/scraping-account-data

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

爬取帳戶資料

概述

用戶在 Playwright 瀏覽器中親手登入;你找出網站自身頁面所使用的資料來源,並在頁面內重放它(使用 session 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)以及詳情端點(開啟一個項目)。
    • GraphQL——一個 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 秒,包含重試機制,使用簡短的 evaluate 輪詢。每個回應:如果是登入/驗證碼頁面(URL 包含 signin/captcha,或預期 JSON 卻收到 HTML),則設定 error 並停止——這些通常以 200 狀態碼返回。
  6. 在導航前先儲存(§3)。任何 goto/重新載入都會清除 window。使用帶有絕對 filename 路徑的 browser_evaluate,返回一個物件(JSON.stringify 會雙重編碼)。每個檔案約 5 MB 是可行的;超過此大小則按批次分割。
  7. 已簽名/不可重放的請求(請求簽章標頭、nonce 主體、拒絕編輯的持久化查詢):訪問每個詳情頁面並被動捕捉其回應(§4)。
  8. 建立 + 驗證(見下方)使用資料目錄外部的解析器腳本,然後建立一個洞察筆記。如果專案已有佈局(例如 tools/<service>/build_db.py、資料旁的筆記),請遵循;否則請提問。

僅讀取。 僅重放頁面本身為顯示資料而請求的內容。GraphQL:根據 operation(query/Get*/List*)判斷,絕不使用 mutation。絕不重新排序、取消、評分、歸檔或刪除。

驗證——請執行所有檢查

檢查項目原因
分頁因遊標/列表耗盡而結束,而非因為錯誤或登入重新導向防止靜默截斷
尋找列表尾端的「在應用程式中檢視較舊訂單」文字網頁版會限制歷史記錄(Swiggy:約 11 個月)
不要只相信網站的計數端點或標頭Blinkit 顯示 40 筆;但列表實際有 83 筆
各元件總和等於每列的總計(項目 + 費用 − 折扣 = 已付金額)抓取解析偏移;如果網站對舊記錄省略了明細行,請說明——不要強制
項目價格總和等於項目小計避免單價與合計混淆
唯一的 ID;對完全重複的資料進行去重匯出和收據會重複列出
按 ID 與另一個來源(匯出、收據)交叉比對證明覆蓋範圍
每個列表/分頁/篩選條件都已涵蓋(已歸檔、已取消、其他年份、子服務)「所有訂單」通常涵蓋多個列表

解析筆記

  • 伺服器驅動的 UI API(snippets、widgets、widget_type、layout):依序遍歷 widget,收集每個 widget 的 text 欄位,並根據已知標籤進行映射。一個只有一個 text 欄位的 widget 通常是下一個 widget 的標籤——將標籤名稱列入白名單,否則每個欄位都會偏移。
  • 金額可能是分/角單位;「FREE」= 0;開頭的「-」= 折扣;刪除貨幣符號和印度千位分組逗號。將貨幣單位分開存放。
  • 時間戳記:購買記錄 → 用戶時區;行程/旅遊 → 記錄當地時間。
  • 將原始檔案標記日期(orders-raw-YYYY-MM-DD.json)存放在建立的 SQLite 旁。

Git

僅提交:.gitignore 行、解析器腳本、任何 README/index 行。原始檔案和 SQLite 保留在本機。明確指定路徑進行暫存(絕不在髒的工作目錄中使用 git add -A);僅在被要求時才提交。

常見錯誤

  • 一個長時間的同步 evaluate 循環——會超時;請在背景執行並輪詢。
  • 將大量資料返回聊天而非使用 filename。
  • snippet 監聽器未卸載——使用 page.off 將它們移除,否則重複執行會疊加處理器。
  • 在 HTML 渲染的網站上只過濾 xhr/fetch,並得出「沒有資料來源」的結論。

Individual skills in this repo

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

相關技能