AI-Chain

把網頁變成可用上下文:Crawl4AI 如何用 Markdown、瀏覽器控制與安全邊界打造 LLM-ready 爬蟲

Crawl4AI 將動態網頁轉成適合 LLM、RAG 與資料管線使用的 Markdown 與結構化資料。本文從非同步爬取、內容降噪、深度爬取到 Docker server 的安全邊界,拆解如何把一次性抓取腳本導入成可觀測、可重跑的來源擷取層。

分享:
把網頁變成可用上下文:Crawl4AI 如何用 Markdown、瀏覽器控制與安全邊界打造 LLM-ready 爬蟲

把網頁變成可用上下文:Crawl4AI 如何用 Markdown、瀏覽器控制與安全邊界打造 LLM-ready 爬蟲

當我們把大型語言模型接上真實世界,最先遇到的通常不是模型不會回答,而是模型拿不到乾淨、可追溯、符合任務需求的網頁內容。傳統爬蟲可以抓到 HTML,卻往往也把導覽列、廣告、Cookie banner、重複連結與無關腳本一起帶進資料集;接著還要自行處理 JavaScript 渲染、分頁、登入狀態、代理伺服器、快取與結構化欄位。這些工程細節若沒有被封裝好,RAG、研究代理與資料管線很快就會變成一堆難以維護的特例。

Crawl4AI 的定位,就是把網頁轉成更適合 LLM、RAG 與資料管線使用的結果。它是一個以 Python 為核心的開源網頁爬蟲與擷取工具,提供非同步瀏覽器控制、Markdown 產生、結構化資料抽取、深度爬取、快取、工作階段與 Docker API server。這篇文章不把它當成「按一個按鈕就能解決所有網站問題」的黑盒子,而是從實作角度拆解它的資料流、控制面與安全邊界,並用一個可重跑的最小範例說明如何開始。

先看結論:它解決的是資料進入模型前的工程問題

Crawl4AI 的核心價值可以濃縮成三件事。

第一,它把瀏覽器自動化與內容清理放進同一個工作流。對會依賴 JavaScript 的網站,單純發送 HTTP request 通常只能拿到空殼 HTML;Crawl4AI 可以透過 Playwright 啟動瀏覽器,等待頁面完成,再輸出經過處理的 Markdown。這讓下游程式不必同時維護一套 requests 流程和另一套瀏覽器流程。

第二,它不只回傳整頁文字。Markdown 產生器可以保留標題、表格、程式碼、連結與引用線索,也能用 BM25 等策略把與目標問題較無關的內容降噪。當資料要送進 embedding 或 context window 時,這個步驟比「把整份 HTML 丟給模型」更容易控制 token 成本與內容品質。

第三,它把抓取的控制權交給呼叫端。你可以選擇 CSS 或 XPath selector、LLM extraction、分塊策略、代理、Cookie、session、hooks、快取與深度爬取策略。這種可組合性適合做成可重跑的資料管線,但也代表你必須明確定義允許抓取的網域、輸出大小、請求時間與憑證使用方式。

安裝與第一次驗證

Crawl4AI 的 pyproject.toml 宣告 Python 3.10 以上,並提供 crwl、crawl4ai-setup 與 crawl4ai-doctor 等命令。若使用 uv,可以建立隔離的專案環境:

uv init crawl4ai-demo
cd crawl4ai-demo
uv add crawl4ai
uv run crawl4ai-setup
uv run crawl4ai-doctor

上游 README 也提供 pip install -U crawl4ai 的安裝方式;在團隊專案中,我更建議把依賴交給 uv 與 pyproject.toml 管理,避免把套件裝進系統 Python。若瀏覽器驅動尚未就緒,可依官方文件補裝 Chromium:

uv run python -m playwright install --with-deps chromium

安裝驗證不應只看 import 是否成功。crawl4ai-setup 負責完成瀏覽器相關的初始化,而 crawl4ai-doctor 可以協助確認執行環境;真正進入資料管線前,還要用一個公開且內容穩定的網址做端到端測試,確認瀏覽器能啟動、頁面能載入,並且 result.markdown 不是空字串。

最小可重跑範例:先取得乾淨 Markdown

最小的 Python 程式只需要建立非同步 crawler,使用非同步 context manager 管理瀏覽器生命週期,再呼叫 arun:

import asyncio
from crawl4ai import AsyncWebCrawler


async def main() -> None:
    async with AsyncWebCrawler() as crawler:
        result = await crawler.arun(
            url="https://www.nbcnews.com/business",
        )
        print(result.markdown)


if __name__ == "__main__":
    asyncio.run(main())

使用 uv 執行:

uv run python crawl.py

這段程式的重點不在於示範某個新聞網站,而在於資料流很清楚:輸入 URL,瀏覽器負責取得頁面,Crawl4AI 將結果轉成可供後續處理的 Markdown。實際服務中不要直接假設所有網址都成功,應檢查結果狀態、錯誤訊息、HTTP 狀態,以及輸出長度;對失敗網址建立可重試佇列,並記錄 URL、時間、錯誤類型與版本。

命令列介面則適合快速檢查或放進簡單的 shell pipeline:

uv run crwl https://www.nbcnews.com/business -o markdown
uv run crwl https://docs.crawl4ai.com --deep-crawl bfs --max-pages 10
uv run crwl https://www.example.com/products -q "Extract all product prices"

第一個命令確認基本 Markdown 輸出,第二個用 BFS 深度爬取限制最多頁數,第三個示範以問題描述驅動資料抽取。這三種模式代表不同的成本模型:單頁抓取適合即時查詢,深度爬取需要限制頁數與網域,LLM extraction 則還要考慮模型費用、延遲與輸出 schema 驗證。

從整頁文字進一步走向可用資料

把 HTML 轉成 Markdown 只是第一層。若目標是建立產品目錄、研究資料集或知識庫,通常還需要結構化抽取。

對格式固定的頁面,優先考慮 CSS 或 XPath。它們不需要額外模型請求,輸出速度與成本較容易預測。例如,先定位商品卡片,再擷取名稱、價格與庫存欄位;如果某欄位不存在,就回傳明確的 null,而不是讓模型猜測。這種方式也比較適合每天大量同步。

對版面不固定但語意相近的頁面,可以使用 LLM-driven extraction。此時要把輸出 schema 視為 API 契約:指定必要欄位、資料型別、空值規則與驗證方式,並保留原始 Markdown 作為除錯證據。模型只應該負責從已取得的內容中抽取,不應該在抽取失敗時默默補造資料。

Crawl4AI 也提供 chunking、query-based filtering 與 BM25 等能力。實務上可以採用分層策略:先用 DOM 與 Markdown 規則去掉明顯噪音,再以查詢詞挑出候選片段,最後才對少量文字做結構化抽取。這比對整頁內容直接進行 LLM extraction 更節省上下文,也能讓錯誤更容易定位。

深度爬取與工作階段:把流程設計成有限狀態機

深度爬取最容易出現的問題不是「抓不到」,而是「抓太多」。一個首頁可能連到分類頁、標籤頁、作者頁、追蹤參數與外部網站;若沒有設定深度、頁數、網域白名單、URL 正規化與去重,爬蟲很快會失去邊界。

因此,深度爬取應該至少記錄以下狀態:待處理 URL、已拜訪 URL、目前深度、錯誤次數、內容雜湊與最後成功時間。對長時間工作,使用快取與可恢復的狀態資料,避免每次失敗都從首頁重跑。Crawl4AI 的深度爬取功能、快取與 resume state 能夠提供這些元件,但資料管線仍要自己決定什麼算是相同頁面,以及哪些內容變更值得重新嵌入。

需要登入或跨多頁操作時,session、cookies 與 browser profile 很有用;但不要把個人帳號的 Cookie 硬編碼到程式或送進不受信任的遠端 API。推薦把認證狀態放在受限的執行環境,使用短效憑證,並讓日誌只記錄 session 的識別名稱,不記錄 Cookie 值或 Authorization header。

Docker API server 的安全邊界比便利的預設值更重要

Crawl4AI 的 Docker server 適合把爬取能力提供給其他服務,但它不應該被視為「在內網就安全」。v0.9.0 將 Docker API server 改為 secure-by-default:預設啟用驗證,沒有設定 token 時綁定 loopback,網路請求 body 被視為不可信的宣告式輸入,並限制可以傳入的瀏覽器控制欄位。這個設計把高權限操作移到 server-side 設定,避免任意呼叫者透過請求 body 注入瀏覽器參數或程式碼。

對自架服務,至少要做到以下幾點:

  • 設定 API token,並透過 TLS terminating reverse proxy 對外提供服務。
  • 只允許必要的 CORS origin,不要用萬用字元掩蓋前端設定問題。
  • 限制每次請求的 URL、頁數、執行時間、輸出大小與並行數。
  • 把爬取工作放進有界佇列,避免大量請求耗盡瀏覽器、CPU、記憶體或磁碟。
  • 對 PDF、截圖與其他 artifact 設定 TTL 和儲存配額。
  • 將 server log 與爬取內容分離,避免把頁面中的秘密或個人資料寫入一般應用程式日誌。

v0.9.3 是 2026 年 8 月發布的安全版本,官方說明修正了五項協調披露問題,涵蓋 PDF 路徑的任意檔案寫入、SSRF、無限制 PDF 大小與頁數、PDF HTML escaping,以及 Docker Playground 的 DOM-based XSS。這些修正說明一個重要原則:外部 URL、PDF 內容與請求 body 都是攻擊者可以控制的資料,不應因為「只是爬蟲」就跳過輸入驗證。

尤其是 SSRF,不能只檢查最初輸入的網址。若 HTTP redirect 把公開網址導向內部 IP,或 DNS 在檢查和實際連線之間發生變化,單次 hostname 檢查就不夠。官方 v0.9.3 說明已在 PDF 路徑逐跳檢查 redirect、限制跳轉次數,並驗證實際讀取回應的 peer IP;自架者仍應依 migration guide 與 security verification checklist 檢查自己的網路政策。

這個工具適合什麼、不適合什麼

Crawl4AI 適合需要把公開網頁轉成 LLM-ready context 的工程團隊,例如建立研究代理的來源擷取層、每日同步文件網站、從多個頁面建構 RAG 知識庫,或把瀏覽器操作與資料抽取整合進現有 Python workflow。它的優勢在於功能面完整,而且可以從單頁 Python 程式逐步擴展到深度爬取與 Docker server。

它不適合被當成繞過網站授權、破解驗證碼、無限制複製資料或替代資料治理的工具。是否允許抓取仍取決於網站條款、robots policy、著作權、個資與企業內部規範。即使技術上可以使用代理、Cookie 或 browser profile,也不代表每個來源都允許這樣做。

它也不會自動保證 Markdown 品質。動態頁面可能需要等待條件,網站改版可能讓 selector 失效,登入頁可能被誤判為成功頁面,LLM extraction 可能回傳不完整 schema。因此,上線前要建立固定測試網址、欄位完整率、內容長度、重複率、錯誤率與延遲指標;對重要資料保留原始輸出與來源 URL,讓每個 embedding 或模型回答都能回溯。

一個可維護的導入順序

我會把導入分成四個階段。

第一階段只做單頁 Markdown。先用固定網址驗證瀏覽器、依賴與輸出,不急著加入 LLM。這能把環境問題與抽取問題分開。

第二階段加入內容清理與 schema。定義哪些標題、表格、連結與引用要保留,為結構化輸出加上型別驗證,並用少量真實頁面建立回歸測試。

第三階段才加入深度爬取、快取與並行。此時先設定 page budget、depth budget、時間上限、網域白名單與失敗重試上限,並量測每頁的成本,而不是只追求吞吐量。

第四階段才考慮 Docker API server 與多租戶。把驗證、TLS、CORS、網路出口、artifact 儲存、工作佇列、審計 log 與秘密管理一起設計。若呼叫端不完全可信,應把它限制在宣告式低權限選項,不要讓請求 body 攜帶任意程式碼或瀏覽器內部控制權。

觀測、驗收與資料品質

把爬蟲接到模型之前,最好先建立一份小型驗收集,而不是等到回答錯誤才回頭找原因。每個測試網址都應有預期的頁面標題、主要內容關鍵字、最低輸出長度與允許的錯誤狀態。測試時同時記錄載入時間、瀏覽器啟動時間、重試次數、產生的 Markdown 大小,以及抽取欄位的完整率。

資料品質可以分成三層檢查。第一層是傳輸檢查:網址是否在允許網域、HTTP 狀態是否合理、是否被導向登入頁或錯誤頁。第二層是內容檢查:標題是否存在、主要段落是否足夠、正文與導覽內容的比例是否異常、引用連結是否保留。第三層是語意檢查:抽取出的欄位是否符合 schema、價格或日期格式是否可解析、同一頁重跑後是否出現不合理的大幅變化。

若資料會進入 RAG,還要保留來源 URL、抓取時間、版本、內容雜湊與分塊識別碼。更新時先用雜湊判斷內容是否改變,再決定是否重新切塊與建立 embedding。這樣可以降低重複成本,也讓模型回答能回到具體來源,而不是只剩一段沒有上下文的向量。

最後的判斷框架

Crawl4AI 的價值不只是「另一個爬蟲套件」,而是把網頁擷取重新包裝成模型資料管線的一個可組合層:瀏覽器處理動態內容,Markdown 降低格式噪音,抽取器把內容轉成 schema,快取與狀態讓工作可以重跑,Docker server 則把能力提供給其他服務。

但這個抽象層越強,邊界設計就越重要。真正可靠的部署應同時回答五個問題:我要抓哪些來源、我要保留哪些證據、每次最多消耗多少資源、外部輸入可以控制哪些欄位,以及失敗時如何重跑而不重複污染資料。只要先把這五個問題寫成程式設定與驗證規則,Crawl4AI 就能從一次性的抓取腳本,變成 RAG、研究代理與資料工程中可觀測、可測試、可維護的來源擷取層。

參考資料