Communitygithub.com

ethanplusai/astro-conversion-kit

以受控、唯讀的方式爬取即時網站,將每個頁面的 HTML、文字與 head 標籤、重導向(包含每一次跳轉)、連結、第三方腳本、媒體資源、樣式表、字型、標誌與圖示、饋送、模板以及三種寬度的即時螢幕截圖存入 capture/ 資料夾,供後續重建比對。在轉換或重建網站前、需要爬取、擷取、快照或盤點網站時,或擷取因阻擋而中斷需要續傳時使用。

astro-conversion-kit 是什麼?

此技能(ethanplusai/astro-conversion-kit)提供一個結構化的管道,用於盤點與擷取即時網站。它能系統性地爬取網站、儲存每個頁面的 HTML 與文字、追蹤重導向、列出連結與第三方腳本、下載媒體與樣式資產,以及產生三種寬度的螢幕截圖,所有資料都存放在 capture/ 資料夾中。其設計專為網站轉換或重建前的準備工作,確保後續步驟可依賴一份完整的本地快照。 此技能的核心功能是其完善的限速機制,能根據伺服器回應(如 429 或 503 狀態碼)自動調整請求間隔與並行數,以避免被封鎖。若網站阻擋請求,則會優雅地停止(退出碼 3)並支援續傳。此外,它還包含資產提取(標誌、圖示、字型)、模板識別(透過 Jaccard 相似度)、可選的 Lighthouse 效能審查,以及一份自動產生的擷取摘要 README。 此技能主要設計用於命令列環境(例如 Claude Code、Cursor 或任何基於終端機的 AI 代理),並作為較大轉換流程的一部分。其「唯讀」(read-only)與「受控擷取」(paced capture)的金律,使其成為任何需要在不修改原始網站的情況下進行精確網站盤點的工具箱中一個可靠且不可或缺的工具。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ethanplusai/astro-conversion-kit/tree/HEAD/skills/capture-site

在你喜歡的 AI 中提問

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

說明文件

capture-site

將即時網站提供的所有內容儲存一次,以便後續步驟都使用這些擷取資料進行。

金律

即時網站是唯讀的,擷取完成後同樣是唯讀的。 腳本只會發出有間隔的 GET 與 HEAD 請求;絕不提交表單、登入,或手動擷取以填補缺口。筆記寫入後,capture/ 下的任何內容都不會再被編輯:它將是所有關卡檢驗的證據。

使用時機

轉換流程的第 2 步(convert-site 會自動執行),或在需要盤點即時網站時(暫存或新網站的盤點是 launch-audit 的工作)。若擷取因錯誤而中斷(退出碼 3),請依照下方說明續傳。

限速

所有腳本都使用桌面版 Chrome 的使用者代理字串。擷取腳本(capture、media、assets、fingerprint)共用一個基於主機的限速器:預設情況下,請求間隔 400 毫秒,最多 4 個請求並行(media:6 個),因此回應快速的網站可在幾分鐘內完成讀取。Chromium 相關步驟(shoot、css-coverage、styles)一次載入一個頁面,間隔 500 毫秒,而 launch-audit 與 pre-launch 則使用自己的限速。限速器會自動調整:

  • 收到 429 或 503 回應時,該主機的延遲時間會加倍(最多 32 倍),並降為一次只能有一個請求;在連續收到 30 秒的正常回應後,會逐步恢復(延遲減半,並行數增加 1),直到回到預設值。
  • 回應時間超過 5 秒時,該主機的並行請求數會減半(在減半期間不會再次觸發),並透過連續 30 秒的正常回應逐步恢復(每 30 秒可再增加 1 個並行請求)。
  • 403 或網路錯誤同樣會計入下方提到的「連續 3 次」停止條件。

--polite 是舊版的限速模式:一次一個請求,間隔 2500 毫秒(適用於 capture、media、assets)。在遇到有機器人驗證牆的共享主機(如 SiteGround 的 /.well-known/sgcaptcha/,或對少量快速請求就回應 429 或 503 的主機)時,或執行因阻擋而中斷時,請從頭使用此模式:以 --polite 續傳。--delay <ms> 與 --concurrency <n> 可以覆蓋預設值或 --polite 設定。對即時網站請保持使用預設值或 --polite(--delay 0 僅適用於本地測試用例),且絕不更改 --ua 來規避封鎖。

  • capture 會預先擷取最多 --concurrency 個佇列中的 URL,並依佇列順序記錄,因此擷取結果等同於逐個爬取。每個 URL 會嘗試 3 次。若嘗試 3 次後仍被封鎖(403、429、503 或網路錯誤),該 URL 會連同其狀態碼與 attempts 記錄在 inventory.json 中(sitemap 或 REST 列表則記錄在 meta.json 的 discoveryErrors 中),爬取會繼續。僅當連續 3 個不同 URL 都用盡嘗試次數且之間沒有成功請求時,才會停止,此時狀態會被儲存,這三個 URL 會以新的嘗試次數重新排入佇列。它絕不請求 wp-admin、wp-login、xmlrpc.php 或 ?s= 搜尋路徑。
  • media 每個檔案嘗試 3 次:如果持續收到 429 或 503,會立即停止;403 或網路錯誤則記錄為該檔案的狀態,且連續 3 個此類檔案(依回應到達順序)會導致停止。已在下載中的檔案會讓它完成。每 100 個檔案會儲存一次 media.json,因此若被終止,續傳時可從接近中斷點處繼續。
  • fingerprint 不會重試:若首頁被封鎖或為機器人驗證頁面,則視為退出碼 3。assets 與 shoot 在連續收到 3 個被封鎖的回應後也會停止。

指令順序

請在將存放 capture/ 的資料夾(即網站儲存庫的根目錄)中執行。<skill-dir> 是此技能資料夾的絕對路徑,位於已執行過 npm install 的套件副本中(腳本會匯入其套件)。每個腳本都會印出 --help 說明,請優先執行此指令而非閱讀原始碼。請依序執行每個步驟:

  1. 指紋辨識,然後閱讀平台參考文件以了解其命名方式(見下方表格):

    node <skill-dir>/scripts/fingerprint.mjs https://www.example.com
    
  2. 擷取。 發現機制包含 sitemap(robots.txt 中的每個 Sitemap: 行,加上平台的預設索引)、REST 列表(WordPress,當指紋辨識發現 REST 時;可使用 --no-rest 跳過)、連結爬取,以及 --seed <path> 或 --seed-file <file>(每行一個路徑或 URL,# 開頭為註解)用於爬取無法觸及的路徑(舊 URL、舊的 .htaccess)。爬取完成後,Wayback Machine 中未找到的路徑會寫入 wayback-unverified.txt(可使用 --no-wayback 跳過;若列表失敗,會等待 10 秒後再嘗試一次,然後才在 meta.json 的 wayback 中記錄 failed)。?p= 短連結會記錄為未驗證,除非傳入 --verify-shortlinks 參數,否則不會擷取。爬取完成後,它會請求一個不存在的路徑(/<32 個十六進位字元>/)一次,以便將網站自己的 404 頁面儲存為 pages/404.html(記錄在 meta.json 的 notFound 中;若網站對該路徑回應 200 或重導向,則不會儲存頁面),並分別請求 /favicon.ico 與 /apple-touch-icon.png 各一次(會跟隨重導向),記錄在 meta.json 的 icons 中(路徑:{ status, file, contentType, bytes });若回應 200,則逐位元組儲存為 assets/root-favicon.ico 或 assets/root-apple-touch-icon.png(若回應為 HTML 則不儲存並附帶 note;若超過 5 MB 則狀態為 "too-large"),且 assets.mjs 會將其以 kind 為 "root-icon" 列出在 assets/index.json 中,包含其 path,以便建置流程將其放置於該路徑。URL 會以大寫的百分比編碼作為鍵值(%c3%a9 與 %C3%A9 視為同一個 URL),因此用兩種拼法連結的頁面只會被擷取一次。robots.txt 中命名但回應 404(或任何非 200 狀態碼)的 sitemap,會連同其狀態碼記錄在 sitemaps/index.json 中,並在 meta.json 的 discoveryErrors 中記錄。位於其他主機上的 sitemap(robots.txt 指向姊妹站點的 sitemap,或索引 sitemap 列表中包含的;www 與 apex 視為同一主機)會記錄為 { url, host, skipped: "other host" },且永不擷取,因此這些 URL 不會進入爬取佇列。兩個檔名相同的 sitemap URL 不會互相覆蓋:第二個會以其目錄路徑作為後綴儲存(例如 page-sitemap-es.xml)。--exclude <prefix>[,<prefix>...] 可將網站的部分路徑排除在外(例如 WordPress 多站點的子站點如 /president/,或網站擁有者保留的區域):路徑以此前綴開頭的 URL 將永不請求,無論是 sitemap、REST 列表、連結或重導向指向它。位於排除前綴下的 sitemap 會記錄在 sitemaps/index.json 中,狀態為 { url, skipped: "excluded" };重導向到排除區域的目標會被記錄但不請求;指向排除區域的連結會保留在已儲存的 HTML 中,但在 links.json 中歸類為 excluded 而非 internal;meta.json 的 excluded 會記錄這些前綴,基準線(baseline)也會帶入。前綴與路徑的比較會進行標準化,因此 /présidence/、/pr%c3%a9sidence/ 與 /pr%C3%A9sidence/ 被視為相同前綴。樣式表或根圖示若重導向到排除區域,則不會跟隨(該樣式表會以狀態 "excluded" 記錄)。--resume 會保留這些前綴;在 --resume 時新增的前綴,會移除已擷取的該前綴下的內容(包括其頁面及對應的 pages/ 與 text/ 檔案、來自該區域的重導向、饋送與 sitemap,以及僅這些頁面使用的樣式表與腳本),並印出已移除的內容。media.mjs 與 assets.mjs 同樣會跳過這些排除前綴下的檔案。

    node <skill-dir>/scripts/capture.mjs https://www.example.com --out capture
    

    然後進行 Wayback 第二階段,當 wayback-unverified.txt 不為空時:它會對每個已存檔的路徑發出一次請求,因此那些仍會重導向的路徑會以來源 seed 記錄在 capture/redirects.json 中(基準線的重導向會拾取它們),而其餘的路徑則會連同其狀態記錄在 inventory.json 中。--seed、--seed-file 與 --include-query 在 --resume 時全部適用,且不會再次詢問 Wayback Machine:

    node <skill-dir>/scripts/capture.mjs https://www.example.com --out capture --resume --seed-file capture/wayback-unverified.txt
    
  3. 媒體。 列出 capture/media.json 中的每個媒體檔案,並儲存至 .conversion/media-cache/(轉換的工作目錄,不納入 git 版本控制):

    node <skill-dir>/scripts/media.mjs --capture capture --download .conversion/media-cache
    

    它會一次下載六個檔案。預設情況下(--sizes referenced),它會擷取原始檔案以及網站使用的所有尺寸:包括被頁面、樣式表、srcset、og 標籤或 sitemap 引用的,或其檔案名稱出現在已擷取頁面、樣式表或腳本中的(data-thumb、data-bg、JSON 設定、滑桿腳本)。WordPress 中僅 REST 媒體列表命名的尺寸,會以 downloaded: false, reason: "unreferenced size" 列出,且不會請求。它會印出分類結果,例如 920 originals + referenced sizes (downloaded), 4,520 unreferenced sizes (listed only):請將此行重複告知使用者。當網站擁有者表示舊的電子郵件或其他網站可能連結到這些尺寸時,請使用 --sizes all。

    透過查詢字串調整尺寸的主機(WordPress VIP、Jetpack Photon:photo.jpg?w=1024、?resize=300,200)所有尺寸都位於相同路徑。原始檔案是裸路徑,因此這是被請求與儲存的物件;每個被看到的查詢字串會列在 variants 下(不請求;--sizes all 會將它們儲存為 <path>%3F<query>,位於兄弟資料夾 .conversion/media-cache-variants/ 中,因此上傳或複製到儲存庫中的媒體快取僅包含裸路徑)。當裸路徑回應錯誤(4xx 或 5xx;重導向會記錄其位置;太大的檔案會在提高上限後再次請求),則會儲存一個變體作為替代,且該條目的 downloadedFrom 會記錄來源 URL。快取破壞用的查詢(不含 w、h、resize、crop、fit、quality、format 或 s 參數,例如 ?ver=3)視為相同檔案,因此它會被優先選用,且不會標記其他項目;否則會儲存最寬的變體,且條目會標示 resized: true。執行時會為每個檔案印出一行,以及一個計數(例如 2 originals unavailable (resized: true) ...),baseline/media.json 會保留這兩個欄位,而媒體關卡會重複此計數為 N resized (original unavailable on live) 但不視為失敗,因為它會比較實際儲存的位元組。請將此計數重複告知使用者,並在計畫與操作手冊中列出這些檔案,標明為即時網站不再提供的原始檔案。

  4. 模板。 將回應 200 的頁面分組為 capture/templates.json。在 WordPress 上,頁面會先根據模板的 body class 分組(home、page、single-post、archive、模板類別),且標記明顯不同的頁面(Jaccard 係數低於 0.5)會分裂為 page-2;其他平台則根據 Jaccard 係數 0.6 合併標記,命名為 template-<n>:

    node <skill-dir>/scripts/templates.mjs --capture capture
    
  5. 資產。 將標誌、favicon、apple-touch-icon、<link rel=manifest> 的網頁 manifest 以及每個 @font-face 字型存入 capture/assets/,此外,當 meta.json 的 icons 記錄為 200 時,還會儲存根目錄的 /favicon.ico 與 /apple-touch-icon.png(root-favicon.*、root-apple-touch-icon.*):

    node <skill-dir>/scripts/assets.mjs --capture capture
    

    標誌會先在首頁的 <header> 中尋找,然後在 class 或 id 包含 logo 名稱的其他元素中尋找(.logo、.site-logo、#logo-wrap)。在每個元素中:優先尋找 src、alt、class 或 id 包含 "logo" 字詞的 <img>(但不包含 "logout"),接著是包含 "logo" 在其 class、id、aria-label 或 <title> 中的內聯 <svg>(儲存為 logo.svg,assets/index.json 中 url: null;若它僅 <use> 了頁面中其他地方定義的 symbol,則無法獨立呈現,其 note 會說明),然後是首頁連結中的第一個 <img>,最後是該元素內的第一個 <img>。請用肉眼檢查 assets/logo.*:帳戶頭像或贊助商標誌仍可能在非標準的 header 中勝出。Favicon 與 apple-touch-icon 會按照其 <link> href 提供的方式儲存(包含查詢字串),因此若指向某個上傳檔案的調整尺寸版本(?w=32、?w=180),其位元組會與 media.json 中該檔案的條目不同:請保留已儲存的圖示,而非原始檔案。

  6. 即時螢幕截圖,每個模板一張,分別為 390、768 與 1440 寬度,使用視覺審查拍攝腳本:

    node <skill-dir>/../visual-review/scripts/shoot.mjs --base https://www.example.com --routes capture/templates.json --widths 390,768,1440 --out capture/screens/live
    
  7. Lighthouse(選擇性)。 僅當 npx --no-install lighthouse --version 有回應時執行;未經詢問絕不安裝;若缺少,請在筆記中說明(跳過,非通過)。執行 mkdir -p capture/lighthouse-live,然後對 templates.json 中的每個 representative 頁面依序執行一次:

    npx --no-install lighthouse https://www.example.com/ --quiet --chrome-flags="--headless=new" --output json --output html --output-path capture/lighthouse-live/home
    
  8. README。 將擷取摘要寫入 capture/README.md;其 ## Notes 部分以產生的行數開頭,每次執行都會重寫(包含 Wayback 第二階段驗證了多少路徑及其回應:狀態碼、重導向目標;Wayback 列表失敗或被拒絕的大小資訊;每個重試後仍失敗的 URL)。請在最末尾執行,以及在任何重新執行之後執行:

    node <skill-dir>/scripts/readme.mjs --capture capture
    
腳本退出碼
fingerprint0 完成,2 用法錯誤或無法連線,3 正在被封鎖或遇到機器人驗證
capture0 完成,2 用法錯誤,3 因封鎖、無法連線、機器人驗證而停止(均可續傳),或沒有頁面回應 200
media0 完成(包含缺少檔案),2 用法錯誤或無擷取或沒有回應 200 的頁面,3 因封鎖而停止
assets0 完成(包含缺少檔案),2 用法錯誤或無擷取,3 因封鎖而停止
templates0 完成,2 用法錯誤、無 inventory.json 或 "未擷取到頁面"(沒有回應 200 的頁面)
readme0 完成,2 用法錯誤或無 inventory.json
shoot0 全部拍攝成功,1 某個路由失敗,2 用法錯誤,3 因封鎖而停止

關於退出碼 3

網站正在阻擋請求或無法連線。請稍候(數分鐘,而非數秒),然後:

  • fingerprint:重新執行。
  • capture:使用 --resume 執行相同的指令。仍在佇列中的 URL 會被重試。

…[內容已截斷,待翻譯]

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ethanplusai/astro-conversion-kit

Convert a live website (WordPress first; Drupal, Webflow, Squarespace, Wix and static sites too) into a static Astro site with the same URLs, content, head tags, media, redirects and look, proven by parity gates and a pixel-level visual review, ending in one pull request, a noindexed staging deploy and a launch runbook. Use when asked to convert, rebuild, migrate or clone a site to Astro, when handed a site URL with this kit's link, to resume a conversion from .conversion/state.json, or with --apply <id> to apply one suggestion as a proposal.

ethanplusai/astro-conversion-kit

Audit a live or staging website and report what would go wrong at launch — crawl and inventory, indexability, redirects for a domain cutover, links, images, forms, accessibility, performance, analytics, content sanity, and full-page screenshots for a visual pass. Use before or right after a site launch, when asked to QA, audit, or review a website, when a site is moving to a new domain, or when somebody asks whether a site is ready to go live. Read-only: it never submits a form, clicks a control, or edits anything.

ethanplusai/astro-conversion-kit

Freeze a site capture into baseline/ and prove an Astro build matches it — every route, redirect (one hop, through a simulation of the host), SEO head field, visible text, internal link, media file, sitemap entry, feed, form, third-party script and security header — with approved differences in exceptions.json and improvements in proposals.json. Use after a capture to build the baseline, when compiling redirects.csv for Vercel or Cloudflare, before calling any conversion page done, when a gate fails and needs reading, or to check a staging deploy against the baseline.

ethanplusai/astro-conversion-kit

The moment DNS moves and for the thirty days after — verifies the cutover (DNS propagation, certificate, http and www redirects, the noindex, robots and sitemap on the live host, every redirect the audit mapped, forms, analytics, the staging copy, the old host, security headers), diffs production against the pre-launch baseline, and schedules the watch. Use when asked did the launch work, is the site live, what should I check after launch, the domain just switched, or when a site went live in the last month and something looks wrong. It is read-only and exits 0 whatever it finds.

相關技能