trafilatura 是一款不需瀏覽器的 Python 內容擷取工具。在本文的標註測試資料中,它唯一能在同類 HTML 擷取品質上正面對決的對手是 Mozilla Readability:trafilatura 只漏掉 17 個已標註的 boilerplate 單元中的 1 個,而 Readability 漏掉了 5 個。以瀏覽器為基礎的工具只在部署體積的脈絡中被提及,並未在這些頁面上進行品質測試。

它的核心工作就是主內容擷取:輸入 HTML,輸出以文章為導向的文字與中繼資料,並透過規則把頁面上的裝飾元素篩掉。它可以把結果序列化成 JSON 和其他格式,但不會產出你自訂的列式 schema,也不會輸出重複的結構化目錄記錄。本文測試的是 2.1.0 版本。它不執行 JavaScript,而與 Readability 的比較也顯示,這比較像是「精準度 vs. 保留內容」的取捨,而不是整體層面的全面勝出。
trafilatura 的定位,以及它刻意不做的事
trafilatura 自稱是可透過 Python 與命令列使用的網路文字與中繼資料蒐集工具,涵蓋爬取、抓取、擷取等用途,並能輸出 CSV、JSON、HTML、Markdown、TXT 或 XML。這個說法很廣;但實際上,真正讓這個工具成立的能力更窄也更清楚:它會接收一份 HTML 文件,並回傳去掉周邊頁面元素後的 主內容。

先建立一個心智模型,因為這能同時解釋它的優勢與邊界。多數你拿去抓頁面的爬蟲都是 selector 驅動——你告訴它「抓 class 是 product-price 的元素」,它就把那個位置上的內容回給你。trafilatura 則相反。它會讀完整份文件,再用內容規則判斷哪些區塊才是文章正文,哪些只是 boilerplate,而不是照你寫的 selector 去抓。這也是它不需要針對每個網站寫清理規則的原因;但也正因如此,它沒辦法直接給你一份結構化目錄:沒有 schema、沒有型別化的列,只有「這裡是有意義的文字」。它是擷取器,不是你直接指定目標的 parser。
它也不需要另外下載瀏覽器執行環境。依賴樹裡包含像 lxml 這類平台 wheel,因此「不用下載瀏覽器」不應被誤解成只靠原始碼或完全不用原生元件的安裝。
安裝體驗:依賴輕、也不用裝瀏覽器
在 Python 3.14 的全新 virtualenv 中執行 pip install trafilatura,總共安裝了 17 個套件;根據 pip-install-trafilatura.log,紀錄到的最大 wheel 是 lxml,大小 8.6 MB。安裝過程不需要另外安裝瀏覽器,也不需要在安裝後執行任何瀏覽器相關指令。
若看規模,這次研究基底中的 Scrapling 套件為了讓 fetcher 正常運作,前後共跑了四次獨立的 pip 指令,最後裝了 26 個套件,其中有兩個是 42.2 MB 的 Playwright driver wheels(tools/scrapling/artifacts/logs/pip-install-scrapling.log)——而這還不包括瀏覽器二進位檔下載。Crawlee 套件則量到另外下載 Chromium 約 81.7 MiB(tools/crawlee/research-materials.md)。那些工具做的是更大的工作,所以這不是能力上的公平對決;這只是你的磁碟與 CI cache 會實際看到的成本。而我拿到的版本(2.1.0)也正好就是目前釋出版本,因此下方數據沒有「你測的是舊版」這種版本落差問題。
實際測試:這個擷取器到底回了什麼

我把它丟進幾個同時涵蓋「強項」與「邊界」的 fixture,原始輸出都保存在 benchmark repo 中。其中,文章測試是最讓我信服的一個。
我拿一個本機文章 fixture,並在真正內容外層塞進各種干擾:登入提示、訂閱提醒、導覽連結、版權頁尾——也就是天真型爬蟲常常連正文一起抓進來的標準 boilerplate。trafilatura 回傳了 標題加上 3/3 段正文,而那些 boilerplate 標記——Login、Subscribe、Copyright——全部都沒有出現在輸出裡。除此之外,它還正確擷取了頁面 metadata 中的 作者與日期。完整結果包含 .txt、.md 與 .json,可見於 results/local_article.json。
同一份儲存下來的 HTML 也各自輸出成純文字、Markdown 與 JSON。本文並沒有證明這三種格式一定是來自同一次同步呼叫;它們只是同一條擷取流程的不同序列化結果。這裡的 JSON 包的是擷取後的文字與中繼資料,不是你自訂的重複記錄。
以下把第一次完整結果整理在同一個地方,方便你對照,而不是只憑我說:
| Fixture | 回傳內容 | 執行時間 | 證據 |
|---|---|---|---|
| 本機文章,外層包有導覽 / 登入 / 訂閱 / 版權 | 標題 + 3/3 段正文,沒有任何 boilerplate 區塊外洩,作者 Thunderbit Research Lab,日期 2026-07-09 | 0.007 s | local_article.json |
| 本機商品目錄 | 12 個商品名稱與對應 12 個價格,以純文字呈現,0 筆結構化列,478 字元 | 0.064 s | local_catalog_extraction.txt |
| 回傳 HTTP 500 的頁面 | fetch_url 回傳 None,沒有拋出例外 | 30.012 s | local_failure_500.json |
| Books to Scrape 商品頁(公開頁) | 1,324 字元的乾淨文字,外加對應的 Markdown 版本 | 0.753 s | public_books_product.txt / .md |
每一列都來自 trafilatura 套件中的 artifacts/raw/trafilatura-test-summary.json——trafilatura 2.1.0、Python 3.14、macOS arm64、單機單次執行。這些時間只能當作觀察值,不能當成正式基準測試結果。
在 500 fixture 上,fetch_url 約 30 秒後才回傳 None,而附近的本機端點都很快。這次執行只能證實「有延遲」,不能證實到底是 retry/backoff、固定 timeout,或其他內部流程造成的。本文沒有驗證 fetch_url 是否支援每次呼叫指定 timeout;目前已證實可行的控制方式,是先用你自己可控的 client 抓取,再把得到的 HTML 交給 trafilatura。

同一組測試也揭露出三個邊界。
第一個,而且是最大的:trafilatura 是內容擷取器,不是結構化爬蟲。 我把它跑在商品目錄 fixture 上。它回傳了全部 12 個商品名稱——以文字形式,以及剛好 0 筆結構化列(依 results/local_catalog_extraction.txt 計算,共 478 個字元的平面文字)。價格也有出來,從 $18.00 到 $51.00,各自獨立排在每個名稱下方。你想要的東西都 有 在輸出裡,但都不是欄位。如果你需要 [{name, price, rating}, …],這工具就不對路,而且怎麼調都不會變——這是設計選擇,不是 bug。

第二個:它不會渲染 JavaScript。 它吃的是靜態 HTML。若你把它指向一個 client-side rendering 的頁面,得到的只會是伺服器在 JS 跑之前送出的內容,而那通常不會是你要的。若你的目標站點大量依賴 JS,就要搭配另外的 renderer;trafilatura 不會幫你補這一段。
第三個,是關於我自己證據的一個提醒:我最早做的那次公開頁面測試,使用的是 商品描述區塊,不是真正的新聞文章,因為公開 sandbox 裡沒有新聞頁。上面的文章清理結果來自受控的本機 fixture。這個結果我信得過——boilerplate 去除非常明確——但我不想把商品頁硬包裝成新聞級擷取的證明,所以研究包裡把它列成一個尚未補上的缺口。後來在 2026-07-14 的追測把這個缺口補上了,結果就在下一節。
真實頁面的 boilerplate 健檢

兩個真實頁面先抓取一次,存成離線 fixture 並附上 SHA-256 hash,之後在沒有網路的情況下重新執行。沒有記錄時間,也沒有標註好的 ground truth。這是針對真實頁面的 boilerplate 健檢,不是完整準確率評分。
| 真實文章 fixture | 原始 HTML | 擷取後正文 | 正文/原始 | 移除的頁面裝飾標記 | 標題 | 日期 | 主機名 | 作者 | 站點名 |
|---|---|---|---|---|---|---|---|---|---|
| Wikipedia,「Web scraping」 | 230,049 bytes | 26,673 bytes | 0.116 | 4/4 | yes | 2005-09-17 | wikipedia.org | null | null |
| Wikinews,「7th Heaven」(封存頁) | 79,716 bytes | 2,200 bytes | 0.028 | 5/5 | yes | 2005-11-29 | wikinews.org | null | null |
兩列都來自 artifacts/results/trafilatura-fidelity-summary.json。檢查的標記包括「Jump to content」、「Privacy policy」、「Powered by MediaWiki」、「This page was last edited」,以及 Wikinews 頁面的「free news source」——這些內容在兩個頁面上都被移除,沒有外洩。
正文/原始比值衡量的是壓縮幅度,不是正確性;被省略的文章內容沒有被評分。這兩個 MediaWiki 模板上的 author 與 sitename 都是 null,而受控的本機 fixture 則有提供作者。這是測試中觀察到的 MediaWiki 特定漏抓,不代表整體署名擷取都可靠。擷取到的日期以工具回傳值為準,沒有再對照 ground truth 驗證。
兩個擷取器、相同的 HTML bytes、同一支評分腳本

在這個研究基底裡,只有一次 trafilatura 與同場比較的測試,而那個比較不是 trafilatura 自己做的。是 mozilla-readability 套件做的,作為控制組:22 個人工標註的 fixture,每個文字區塊都標上 ARTICLE 或 BOILERPLATE,且每個字都帶有唯一的 sentinel token,這樣擷取到的字就能精準對回唯一一個標註區塊。兩個工具拿到的是完全相同的 HTML bytes。Readability 跑在 jsdom 29.1.1 與 Node v22.22.3 上;trafilatura 則使用它自己的 parser。
| 指標(micro-averaged,content-fidelity set) | trafilatura 2.1.0 | @mozilla/readability 0.6.0 | 證據 |
|---|---|---|---|
| 找回的 article units | 40/40 | 40/40 | comparison.json |
| 外洩的 boilerplate units | 1/17 | 5/17 | comparison.json |
| 污染輸出的 boilerplate tokens | 3 | 41 | comparison.json |
| Token precision | 0.939 | 0.902 | comparison.json |
| Token F1 | 0.969 | 0.948 | comparison.json |
非散文召回率,f6_nonprose fixture | 7/8 | 8/8 | comparison.json |
極短文章,f3_short_120 的 F1 | 0.571 | 0.800 | comparison.json |
來源:本研究基底中的 tools/mozilla-readability/artifacts/raw/comparison.json——content-fidelity set 裡有 11 個 fixture、40 個 article units 與 17 個 boilerplate units。這些都是刻意偏向對抗情境的合成 fixture,所以應該把它們看成機制展示,而不是實際語料的排行。
兩個工具都不是全面通吃,而這個落差才是最有意思的地方。trafilatura 會把雜訊擋掉——只漏 1 個區塊,Readability 漏了 5 個;污染 token 只有 3 個,Readability 則有 41 個。這就是「乾淨文章文字」的精準度那一半,而這一半往往決定你的 LLM context window 會不會被側欄連結塞滿。但 Readability 也會保留 trafilatura 捨棄的內容:在非散文 fixture 中,trafilatura 丟掉了 <figcaption>,但 Readability 保留了;而在極短文章上,它拿到 0.571,低於 Readability 的 0.800。更激進的清理是取捨,不是白得的優勢。如果你的語料充滿短文、圖說與大量表格頁,這個取捨對你就未必有利。
如何把這個比較變成選型測試
先定義:在你的流程裡,哪一種錯誤成本比較高。如果頁面裝飾會吃掉下游 token,或污染搜尋結果,那麼 boilerplate 外洩數與污染 token 數就應該給更高權重。如果漏掉圖說、短文或非散文區塊無法接受,那麼就該更重視依頁面形狀而定的內容召回率。這組共用 fixture 能把這個取捨顯示出來,但它不會替新聞資料庫、文件語料或檢索流程決定權重。
更完整的壓力測試脈絡,可參考 十個函式庫的記憶體與錯誤 HTML 比較。
請用已儲存的 HTML,而不是即時 URL 來做對決,這樣兩個擷取器才能吃到完全相同的 bytes。應該納入一般長文、短通知、圖說很多的文章、表格或程式碼很多的文件,以及你實際會 ingest 的每一家出版來源模板。在執行任何工具前,先標註少量必需內容單元與已知的頁面裝飾區塊。接著分別評分:空輸出、必需內容回收、非預期內容外洩,以及中繼資料欄位。單一的整體「品質分數」往往會遮住真正重要的失敗模式。
同時也要往下游驗證輸出契約。trafilatura 的 JSON 可以包含擷取內容與中繼資料,但 JSON 序列化不等於你自訂的型別化列 schema。針對文章文字,應該檢查最低正文長度與必要標記,而不是只要非空輸出就算過。針對中繼資料,必須區分「缺失」與「錯誤值」,並保留來源 URL 與擷取版本,方便之後重現漏抓案例。
抓取本身也應該被當成獨立層來測。前面那個 30 秒本機失敗觀察屬於 fetch_url,不是屬於已經拿到 HTML 後的擷取;其內部機制也沒有被釐清。如果你在意 deadline、重試、驗證或 proxy 政策,請用你能控制行為的 client 抓取,記錄最後拿到的 response bytes,再把那些 bytes 交給擷取器。這樣可以把 acquisition 失敗與內容選擇失敗切開,讓比較結果更可重複。
最後,部署屬性也要在目標平台上測。這次 17 套件的 Python 3.14 安裝不需要瀏覽器,但這不能代表吞吐量、記憶體成長、所有架構上的 wheel 可用性,或多 worker 並行時的行為。本文證實的是它和 Readability 之間一個有用的精準/保留機制;真正能不能上線,還是得看你的語料與 runtime 測試。
若你想看一個不是本研究基底自己做的外部交叉驗證,trafilatura 的 官方評測頁 與公開的 ScrapingHub article-extraction-benchmark 都顯示,它在約 181 個真實頁面的 word-F1 上優於 readability-lxml——方向與上表一致。不過多數引用那份 benchmark 的文章會跳過一個細節:廣為流傳的 trafilatura F1(約 0.945)是舊版 0.5.1 的數字,不是這裡測試的 2.1.0。
優缺點
優點:
- 在共用 fixture 集上,相較 Readability 漏掉更少已標註 boilerplate:17 個裡只有 1 個,而對方是 5 個。
- 在本機 fixture 上正確抓到作者與日期;在兩個真實文章頁上也正確抓到標題/日期/主機名。
- 同一份 HTML 可序列化成文字、Markdown 或 JSON。
- 只需 17 個套件即可安裝,且不需要另外的瀏覽器 runtime。
- 失敗時很安靜:
fetch_url遇到 HTTP 500 會回傳None,不會丟例外。 - 測試版本就是最新版(2.1.0)——沒有版本落差問題。
- Apache-2.0 授權——寬鬆,商業使用友善。
缺點:
- 不是結構化爬蟲:商品目錄測試只回傳 12 個名稱與 12 個價格的文字,沒有任何型別化列。沒有 schema,也沒有欄位。
- 不會渲染 JavaScript——只支援靜態 HTML;如果目標頁是前端渲染,得另外接 renderer。
- 在兩個真實 MediaWiki 頁面上,
author與sitename都是 null,所以署名擷取並非理所當然。 - 清理過頭有代價:它丟掉了 Readability 保留的
<figcaption>,而且在極短文章上的 F1 只有 0.571,低於 Readability 的 0.800。 - 那次安靜的 500 回應花了 30.012 秒才回傳
None;如果你在意 deadline 控制,請使用你自己可控的 fetcher。 - 內建的 crawl/sitemap spider 與 CSV/XML 輸出格式這次沒有測到,所以我不對它們下結論。
適合誰,不適合誰
trafilatura 的目標是以文章為中心的主內容擷取。若你要從靜態 HTML 建立文字語料、可讀性較高的文章檔案庫,或 NLP 輸入,而且接受以規則來清理頁面,它是值得考慮的候選。共用 fixture 的比較顯示,它的 boilerplate 外洩低於 Readability,但 Readability 在短內容與非散文案例上保留更多。
如果你真正需要的是結構化擷取——像是有價格的商品列、型別化記錄、key: value 欄位——那就不要選它,因為它給你的是文字,不是表格(目錄測試回收了全部 12 個名稱與 12 個價格,但 0 列)。如果你的目標頁內容是由瀏覽器渲染,而且你不打算另外接一個 renderer,也不適合用它,因為 trafilatura 只讀靜態 HTML,讀到這裡就停了。若你的語料大多是短摘要、圖片圖說與表格密集頁,也要多想一層:在標註 fixture 上,這正是它把真正內容一起清掉的地方(極短文章 F1 只有 0.571,且丟掉了 <figcaption>)。選工具要對準工作:完整文章文字可以;結構化 JSON、JS 頁面,或 100 字左右的短文,請找別的方案。
替代方案,以及 Thunderbit 的位置
trafilatura 是 Apache-2.0 的自架式函式庫,沒有供應商按次收費;但算力、頻寬、抓取、監控與維護成本仍由營運方負擔。它能處理你提供的 HTML 進行文章導向擷取,但不處理瀏覽器執行,也不支援你自訂的重複列 schema。
若要看同一組 fixture 在六個擷取器上的比較,請參考 六款函式庫的擷取比較。
託管式服務則可以把 acquisition、rendering 與 schema shaping 放到供應商邊界內。我們打造了 Thunderbit,但沒有用這些 fixture 實測它,因此本文不提供任何品質、渲染、延遲、反機器人或成本比較。差別在於:你要自己掌控 HTML 到內容的流程,還是把 acquisition 與結構化擷取交給雲端服務。
相關 benchmark 評測還包括:完整的開源爬蟲比較、Crawl4AI 的瀏覽器型 Markdown 評測,以及 Firecrawl 的自架式 Markdown 評測。
結論
如果你的工作是從靜態 HTML 做文章導向擷取,而且優先目標是排除標註過的 boilerplate,那麼可以考慮 trafilatura。在共用 fixture 上,它只漏出 1 個已標註 boilerplate 單元,而 Readability 漏了 5 個。這個優勢伴隨著在極短內容與非散文 fixture 上較低的保留率,所以最後還是要看語料形狀來決定。
它不會執行 JavaScript,也不會輸出你自訂的重複列。兩個 MediaWiki 頁面上的 author 與 sitename 都是 null,這是模板範圍內的觀察。Readability 保留了 trafilatura 丟掉的圖說,且在標記為 f3_short_120 的 fixture 上分數更高;可見的證據支持的是「在極短 fixture 上 F1 較低」,而不是字數比較少或輸出被破壞的說法。
試用 Thunderbit 進行網頁資料擷取 Get Started Free
常見問題
trafilatura 會回傳什麼樣的結構? 它可以把擷取內容與中繼資料序列化成 JSON、Markdown、文字、HTML、XML 或 CSV。這屬於結構化序列化,但不是你自訂的重複列 schema,例如商品名稱、價格與評分。商品目錄 fixture 回傳的是平面內容,而不是型別化列。
trafilatura 能把商品目錄抓成結構化列嗎? 不能。它是內容擷取器,不是結構化爬蟲。在商品目錄 fixture 上,它回傳了全部 12 個商品名稱的平面文字,以及 0 筆結構化列——名稱有在輸出裡,但不是欄位。如果你需要像 name/price/rating 這種型別化記錄,請改用 selector-based parser 或 schema-driven 的擷取 API。
trafilatura 會渲染 JavaScript 嗎? 不會。它只處理靜態 HTML。若你把它指向 client-rendered 頁面,拿到的只會是 JavaScript 還沒執行前伺服器送出的內容,而那通常不是你要的。若目標站點大量依賴 JS,請另外搭配 renderer。
trafilatura 安裝起來會不會很麻煩?
在測試的 Python 3.14 virtualenv 中,安裝過程拉了 17 個套件,且不需要另外的瀏覽器 runtime。最大記錄到的 wheel 是 lxml,8.6 MB。另有一個本機 500 呼叫花了 30.012 秒才回傳 None;如果你需要可驗證的 deadline,請使用你自己可控的 HTTP client。
trafilatura 可不可以商用? 它採用 Apache-2.0 授權,寬鬆且適合商業使用。不過在實際採用前,仍建議先到 repo 再確認目前的授權狀態。


