MarkItDown 常常被歸到網頁爬蟲那一類,但這個分類其實不對。它沒有 crawler,沒有 JavaScript 執行環境,也不能抓取網址後把頁面上的樣板內容清掉。它真正做的,是把你手上已經有的檔案——PDF、Word 文件、試算表、簡報——轉成語言模型可以讀的 Markdown。
我花了幾週時間,在一台 Mac 上把 Microsoft 的 MarkItDown 實際跑過一輪真實文件測試:先寫好一份清單逐一比對每個表格,再統計每次轉換所花的時間。簡單講結論:在乾淨的輸入上,它速度快、內容還原度高;但安裝包裡悄悄帶進了一個你未必想要的 73 MB 機器學習執行環境;而且它的表格轉換會出現一些問題,雖然能通過「文字有沒有保住」的檢查,卻可能在「資料是不是還在正確欄位」這關失手。以下就用數據把整體表現說清楚。
MarkItDown 到底是什麼
MarkItDown 是 Microsoft 推出的 Python 工具,可將檔案與 Office 文件轉換成適合 LLM 使用的 Markdown。你可以丟給它 PDF、.docx、.xlsx、.pptx、圖片、HTML 檔,或其他幾種格式,它就會回傳 Markdown。它提供三種使用方式:命令列介面(markitdown file.pdf -o out.md,或從 stdin pipe 進去)、Python API(MarkItDown().convert(...)),以及可選的 MCP server,方便整合 agent 工作流程。

最重要的界線,是它不做什麼。README 本身就沒有宣稱,而且我在測試中也確認了:它不會爬站、不會渲染 JS、不會跟著連結往下抓、不會翻頁,也沒有類似 readability 的主內容抽取。它是一個整體文件轉換器。你把檔案交給它,它幫你標準化。這個差異,決定了它到底適不適合放進你的技術堆疊,所以後面我會反覆提到。
就 GitHub 的外在數字來看,這個 repo 很重量級——截至 2026 年 7 月中旬,有 165,282 顆 star 和 11,790 個 fork,採 MIT 授權,最新版本(v0.1.6)則是在 2026-05-26 釋出。不過,這個 star 數更多反映的是 Microsoft 團隊加上整體 LLM 工具熱潮,不能直接等同於轉換核心本身已經很成熟。它還有 833 個 open issue,其中有幾個在你安裝之前就值得先注意(下面會說)。
HTML 轉 Markdown:又快又完整,但也會把樣板一起帶上
因為我這系列爬蟲評測都會用同一組四個網頁樣本,所以我也把一模一樣的本機 HTML 檔餵給 MarkItDown——不是要拿它當爬蟲評分,而是想看它的 HTML 轉 Markdown 做得好不好。對於標記清楚的頁面,它表現其實相當不錯。
這四個頁面只靠核心安裝就能全部轉完,不需要額外套件,而且每一個正文重點都保住了。Wikipedia 的 “Web scraping” 條目(226 KB)輸出後,標題階層幾乎完整對應:1 個 h1、7 個 h2、12 個 h3,和原文結構一致;418 個連結也都保留成正確的 [text](url)。Scrape This Site 的 forms 頁面 上那個 25×9 的冰球統計表,則變成乾淨的 27 列 GFM pipe table(表頭 + 分隔列 + 26 筆資料列),連空白欄位都完整保留。速度也很漂亮:小型 quotes 頁面的中位數是 48 ms,226 KB 的 Wikipedia 頁面也只有 352 ms。
但這裡有個關鍵限制,這不是 bug,而是設計選擇。MarkItDown 不會移除 boilerplate。它會把整個 <body> 都轉出來,所以網站框架內容也會一起出現,而且頁面越多樣板,殘留就越多。
| 頁面 | 輸出字元數 | 標題數量(h1/h2/h3) | 連結數 | 網站樣板行占比 |
|---|---|---|---|---|
| Books to Scrape | 10,478 | 1 / 0 / 0 | 94 | 0.6%(1/159) |
| Quotes to Scrape | 2,973 | 1 / 1 / 0 | 55 | 1.2%(1/86) |
| ScrapeThisSite forms | 3,385 | 1 / 0 / 0 | 31 | 6.7%(5/75) |
| Wikipedia Web scraping | 60,159 | 1 / 7 / 12 | 418 | 12.4%(42/338) |
在幾乎沒有頁面框架的 Books 首頁上,輸出行裡只有 0.6% 是樣板內容。Wikipedia 則高達 12.4%——338 行非空白行裡,有 42 行是像「跳到內容」、「切換目錄」、「22 種語言」、「摘自……」、Cookie 與授權頁尾這類內容。Wikipedia 的維護提示(例如「本文需要更多引用來源」)甚至會被忠實轉成雙欄 pipe table,這也是為什麼一個沒有真正資料表的頁面,最後會多出 9 行表格。
這些都不是 MarkItDown 做錯了。它是整體文件轉換器,不是 readability 抽取器:忠實把 HTML 轉成 Markdown,和只保留文章主體,是兩種不同工作。Trafilatura 或 Firecrawl 這類工具的目標,是只回傳主內容;MarkItDown 則是把整個頁面都還原出來。從實作上看,它的 _html_converter.py 會先去掉 <script> 和 <style>,然後把整個 body 交給 markdownify,路徑中根本沒有任何主內容判斷。若你只想拿文章正文,這不是對的層級。
它真正的主場:PDF、DOCX、XLSX、PPTX
文件才是 MarkItDown 的本業。我拿它去測幾個真實公開檔案:一篇有文字層的 arXiv 論文、Bitcoin 白皮書、我刻意轉成完全沒有文字的掃描 PDF,以及 MarkItDown 自己測試套件裡的 DOCX/XLSX/PPTX 檔(我還加了 UUID 標記,方便抓出靜默遺失內容的情況)。
| 文件 | 輸入大小 | 輸出字元數 | 檢查點 | 中位數時間 | 備註 |
|---|---|---|---|---|---|
| arXiv 1706.03762(有文字層 PDF) | 2.2 MB | 40,174 | 7/7 | 3.7 秒(warm) | 標題、"Transformer"、"BLEU"、"References" 全都存在 |
| Bitcoin 白皮書(9 頁 PDF) | 184 KB | 22,485 | 6/6 | 1.4 秒 | "Satoshi Nakamoto"、"proof-of-work"、"Conclusion" 都有保留 |
| 掃描 PDF(沒有文字層) | 89 KB | 0 | 0/4 | 15 ms | 輸出空白、沒有錯誤、也沒有 OCR |
| DOCX(test.docx) | 136 KB | 4,651 | — | 70 ms | 標題 + GFM 表格;嵌入的 UUID 都還在 |
| 含公式的 DOCX | 15 KB | 240 | — | 101 ms | Office Math 以 LaTeX 形式保留 |
| XLSX(test.xlsx) | 12 KB | 808 | — | 57 ms | 每個工作表 → ## SheetName + GFM 表格 |
| PPTX(test.pptx) | 278 KB | 2,047 | — | 52 ms | 保留投影片編號標記、表格,圖表也轉成表格 |
在有文字層的 PDF 上,文字召回率非常高——arXiv 的「Attention Is All You Need」論文 7 個預先定義檢查點全中,Bitcoin 白皮書也 6/6 全中。Office 檔案則沒有丟失任何 UUID 哨兵,表示它們在 maintainers 自己的回歸測試樣本上沒有出現靜默內容遺失。還有一個很實用的小勝利:DOCX 路徑(透過 mammoth)會把 Office Math 公式保留成 LaTeX,能把 equations.docx 轉成真正的 $$...$$ 數學式。如果你要把大量含數學內容的 Word 文件丟給 LLM,這是一個非常具體、但相當有用的優勢,我在別處幾乎沒看到有人提過。
這個主場有兩個發現特別值得單獨拉出來說,因為它們最可能在你實際使用時踩雷。
會直接消失的掃描 PDF
如果你丟給 MarkItDown 一個只有圖片、沒有文字層的 PDF,它會回傳空字串。0 個字元、沒有例外、也沒有警告——因為裡面本來就沒什麼可抽取,所以 15 ms 就結束了。MarkItDown 的 PDF 路徑只做文字擷取(底層是 pdfminer 和 pdfplumber),核心安裝與任何 pip extra 都不包含 OCR。
這在批次處理時差很多。若開發者把一整個 PDF 資料夾丟進去,裡面有些是掃描檔,這些檔案就會默默變成空結果,而且完全沒有訊號告訴你有東西被跳過了。我還特地用 pdfminer 的 extract_text 直接驗證過這個測試檔,結果也是 0 個字元、沒有文字層,確認不是 fixture 壞掉,所以空輸出就是 MarkItDown 面對真實掃描檔時的實際行為。這也重現了一個長期未解的 OCR fallback 缺口(#1268)。官方文件中建議的做法是使用可選的 Azure Document Intelligence 後端或 plugin;但這些都不在預設安裝裡。
PDF 會變成扁平文字,不會保留結構
在兩份有文字層的 PDF 上,MarkItDown 都沒有產生任何 Markdown 標題標記。PDF 本身沒有語意化的 heading tag,而 MarkItDown 也不會根據字型大小去推測,所以每一行最後都只會落在 body 層。文字召回高,但結構是平的。
這不只是我的觀察。第三方公開基準測試給 MarkItDown 的 PDF 標題階層分數大約是 0.0,表格保真度大約 0.27,明顯低於 Docling 在 TableFormer 支援下的 0.88(可參考 MarkItDown vs Docling vs Marker 比較 以及 READoc benchmark)。我的測試結果和這些基準是一致的,這反而讓證據更完整——我的數據與外部來源相符。不過,同一批基準也指出,MarkItDown 的速度大約比 Docling 快 100 倍,這也和我在文件上量到的「幾秒而不是幾分鐘」很吻合。重點很簡單:MarkItDown 給你的是乾淨、快速的 PDF 文字,不是 PDF 的 結構。如果標題和表格必須原封不動保留下來,像 Docling 或 Marker 這類版面模型工具才是正確層級。
表格:文字通常會保住,但結構不一定
表格最能看出「文字有沒有保住」和「資料還能不能用」其實是兩件不同的事。所以我做了一個 13 種案例的矩陣——每個案例對應一個 <table>,並以跑前先寫好的 manifest 逐一評分——來精準對照哪些表格形狀能撐住,哪些會壞掉。

結論先講:MarkItDown 從來沒有丟掉表格內容。13 個案例的預先定義 token 都 100% 保留了下來。但結構保真度就分成三種情況。13 個案例裡有 7 個輸出了格式正常的 GFM grid(普通表格、表頭 colspan、24 欄超寬表格、無表頭、空欄位、cell 內含 block、以及由右向左的阿拉伯文表格)。另有 4 個表格變得破破爛爛,因為 Markdown 根本沒有 span cell 的概念,所以 rowspan、colspan 和原始 HTML 不完整的表格都會產生短列。還有 2 個則是直接壞掉。
這兩個壞掉的案例值得點名。一個是巢狀表格(<td> 裡又放了一個 <table>),會被直接攤平塞進父表格的同一格裡,連內層的 pipe 和分隔列一起倒進去,最後變成一列 14「欄」的垃圾資料。另一個問題是,儲存格裡的字面 | 沒有被跳脫——像 a | b 會被拆成兩欄,x || y 甚至會變成三欄——於是原本兩欄的表格,最後會跑出兩欄、三欄、四欄混在一起的列,任何下游 Markdown parser 都會讀錯邊界。反而 cell 裡的星號和反引號都有被跳脫,只有 pipe 沒有。根本原因是 MarkItDown 的 HTML 路徑直接用了 markdownify 的預設 table 處理,而它自訂的 subclass 只改了連結、圖片和標題,沒有接手 table cell。這種 pipe 跳脫問題在 CSV converter 也有一個 開放中的 issue(#2019),但那個修正並不會影響我這次測到的 HTML 路徑。
其中最隱晦、也最值得資料工程師注意的,是 rowspan。案例 t03 不只是變亂而已,它會悄悄把資料對歪。rowspan=2 的標籤("Fruit")只輸出一次,下面那列就變成短短的兩欄(| Banana | 8 |),結果「Banana」跑到 Group 欄,而不是 Item 欄。字都還在,但如果下游程式只看第二欄,就會拿錯值。這就是那種能通過文字存活檢查、卻會靜悄悄污染資料集的 bug。
這個 span 限制本身就是已知且被追蹤的設計限制(#1211、#1248)——平面的 GFM pipe grid 本來就無法表達 span 或巢狀結構,所以轉換器是拿結構去換內容完整性。不過它也不是全都不好:無表頭表格會自動補上一列空表頭(避免資料被靜默提升成標題),空白儲存格會保留,<caption> 也會作為表格上方的一行文字被留下。
安裝與啟動:這個「輕量工具」沒先告訴你的成本
整份測試裡,最讓我意外的就是這一段;也正是在這裡,「輕量 Python 工具」這個說法開始有點超賣。

第一,不要跑 pip install 'markitdown[all]'。在 Python 3.14 上,它會悄悄倒退安裝成 markitdown 0.0.2——一個兩年前的版本——這點我在乾淨的 venv 裡實測過。為什麼會這樣,從 pin 就看得出來:pip install 'markitdown[all]==0.1.6' 會直接報錯,因為 [all] extra 會鎖定 youtube-transcript-api~=1.0.0,而在目前的 PyPI 上,該範圍內的每個版本都限制 Python <3.14,只有相容 3.14 的版本又不在這個 pin 範圍內。於是 resolver 只好一路回退到最後一個能滿足依賴的版本。這也對應到一個 open upstream issue(#2179)。解法很直接:先固定版本,再分開安裝 extras——pip install 'markitdown==0.1.6',然後再 pip install 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6'。這樣都能正常安裝;只有合併式的 [all] bundle 帶有這個有毒 pin。(這個陷阱和 Python 版本有關——如果是 Python 3.13 或更舊,限制不一定會踩到,所以 [all] 的解析結果可能不同。)
第二,是體積。核心安裝包總共是 161 MB(13 MB 空 venv + 148 MB 套件)。其中 onnxruntime(73 MB)和 numpy(34 MB)合計 107 MB,占了整個核心體積的 66%;而這兩個套件又是被一個硬依賴:magika(Google 的 ML 檔案類型偵測器)拉進來的。也就是說,一個文字轉換器在核心安裝時,就已經帶著 73 MB 的 ONNX 推論執行環境,還沒算任何文件額外套件。把文件 extras 也加上去後,venv 會長到 310 MB。這比 headless browser stack 輕很多,但如果你原本以為它是個 pip install 完就能用的微型工具,那就要知道它其實還會拖著一個 ONNX runtime 一起上車。
第三,這一點是我整組測試裡唯一一個完全通過所有新奇性檢查的發現:即使是乾淨安裝後,import markitdown 在這台機器上也要花大約 3.35 秒。而且這幾乎全是 import 時間的成本:markitdown._markitdown 會主動載入整個 converter registry(累積 2.56 秒,占總時間 76%),接著又把 pandas(1.21 秒,來自 XLSX converter)、python-pptx(427 ms)、magika(354 ms)和 requests(270 ms)一併拉進來——不管你有沒有要轉這些格式。對長期運行的服務來說,這個成本會被攤平,不算什麼;但對 CLI 執行或 serverless cold start 來說,這就是每個 process 都要付的真實稅金,而「輕量工具」這個標籤並沒有讓人預期會有這麼大的開銷。(公平提醒:這是單次 profile 結果,當作一個觀察值,不是多次分布。)

規模測試:不會當掉,但 PDF 要預算 CPU,試算表要預算 RAM
我把四個大型檔案各自放到獨立 process 裡跑,避免前一次執行影響峰值記憶體。沒有任何一個掛掉,但成本結構很不平均。

| 主體 | 輸入大小 | 輸出字元數 | 中位數時間 | 峰值 RSS 增量 |
|---|---|---|---|---|
| NIST SP 800-53r5(492 頁 PDF) | 6.07 MB | 1,625,365 | 192.5 秒 | +40 MB |
| XLSX 50,000 列 × 8 欄 | 2.1 MB | 3,722,955 | 62.1 秒 | +374 MB |
| arXiv 1706.03762(約 15 頁 PDF) | 2.2 MB | 40,174 | 12.6 秒 | +25 MB |
| XLSX 200 列 × 64 欄 | 46 KB | 120,129 | 2.9 秒 | +22 MB |
NIST SP 800-53r5 的 492 頁 PDF 中位數花了 192.5 秒——大約 3.2 分鐘,也就是 0.39 秒/頁——因為 pdfplumber 會對每一頁做 word-position form-detection。峰值 RSS 只增加 40 MB,所以瓶頸是 CPU,不是記憶體。甚至那份 15 頁的 arXiv PDF,在獨立 process 裡也要 12.6 秒;這比同一份檔案在我的文件套件中 warm 執行時的 3.7 秒慢了約 3.4 倍。那個差距就是 cold-process 成本,也證明了真正主導速度的不是檔案原始大小,而是每頁要做的工作量。如果你只想記住一個這份 PDF 的可移植數字,那就用獨立測試的 12.6 秒。
試算表路徑則是另一種瓶頸。2.1 MB、50,000 列的 XLSX 檔,峰值 RSS 暴增到 +374 MB(輸出字元數也達到 370 萬),因為 converter 會把整張 sheet 一次載入,然後在記憶體裡組成一整大段 Markdown。最實用的建議很直接:大型 PDF 要預留幾分鐘 CPU;大型試算表要預留數百 MB RAM。這些數字都是在 macOS arm64 與 Python 3.14 的單機測試結果,每頁與每列的常數會受平台影響——但整體形狀(PDF 慢且吃 CPU、XLSX 吃記憶體、沒有當機)是可移植的。
Thunderbit 適合放在哪裡——以及不適合放在哪裡
這裡很容易誇大對比,所以我先把界線畫清楚:MarkItDown 和 Thunderbit 解的是相鄰問題,不是同一個問題。
MarkItDown 是把你已經拿到的檔案轉掉。Thunderbit 則是先抓取網頁內容。Thunderbit 的 /distill 端點 可以把即時網頁轉成乾淨、可直接給 LLM 使用的 Markdown——它負責處理 JavaScript 渲染、反機器人機制與動態內容,這些 MarkItDown 都沒有能力處理——而它的 /extract 端點回傳的是 schema 對應的結構化 JSON,不只是原始 Markdown。對開發者來說,這些能力可以透過同一套 AI 引擎以 API(POST /distill / POST /extract)、MCP server,以及 CLI(npx @thunderbit/thunderbit-cli)的方式使用,也就是那個支撐 100,000+ 使用者擴充套件 的引擎。
所以它們只有一個交集——都能輸出「適合給 LLM 的 Markdown」——但輸入來源不同:Thunderbit 的 distill 針對的是公開網路上的網址,MarkItDown 針對的是本機檔案。它們不是可直接互換的產品,我也不會假裝它們是一樣的。比較實際的做法,是兩者一起用:先用 Thunderbit(或 Firecrawl 類型的服務)抓取與爬行網頁,再用 MarkItDown 去標準化你手上那些混合型本機文件——PDF、簡報、試算表。前者負責網路,後者負責檔案櫃。
優點與缺點
優點
- 乾淨 HTML 的整體內容召回率高(4/4 頁),標題樹與連結都能忠實保留
- PDF/DOCX 文字召回率高(arXiv 7/7 檢查點、Bitcoin 6/6),而且在 maintainers 自己的 Office 測試檔上沒有靜默遺失內容
- Office Math 公式可保留為 LaTeX——這是很少見但很實用的優勢
- 在各種規模測試中都沒有當掉,從 492 頁 PDF 到 5 萬列 XLSX 都撐住了
- 呼叫方式很簡單:CLI、
convert()、stdin pipe,以及可選的 MCP server - MIT 授權、由 Microsoft 積極維護、issue 回應也算積極
缺點
- 會保留樣板內容——Wikipedia 上最高可達 12.4% 的樣板行;它不是文章抽取器
- 表格在 span、巢狀結構與 cell 內 pipe 上容易壞掉(13 個案例中 2 個直接壞、4 個破碎不齊),而且 rowspan 會悄悄把資料對歪
- 掃描/只有圖片的 PDF 會在沒有 OCR、也沒有錯誤提示的情況下回傳空白輸出
- PDF 輸出完全沒有標題結構(這也和公開 benchmark 的結果一致)
- 核心安裝就有 161 MB,還帶著 73 MB 的 ONNX runtime;冷啟動 import 約 3.35 秒
[all]extra 在 Python 3.14 上會悄悄回退到兩年前的 0.0.2 版本
誰該用,誰不該用
如果你的工作是把一堆混合型本機文件——Word、Excel、PowerPoint、有文字層的 PDF——標準化成 Markdown,然後送進 LLM pipeline,而且你更在意文字完整度而不是結構保留,那就很適合用 MarkItDown。把它當成批次作業的最後一哩,把乾淨文字送進模型,它又快、又忠實、而且免費。
但如果你的需求屬於以下任一種,就別單獨靠它,最好搭配別的工具:你只想要網頁上的主文章內容(用 readability 或 Firecrawl 類型工具);你需要 PDF 的標題與表格原封不動保留(那是 Docling 或 Marker 的領域);或者你的輸入包含需要 OCR 的掃描文件(你需要 Azure 後端或完全不同的工具)。如果你本來以為自己在找的是 scraper——也就是能抓取與爬行的東西——那它完全不是這個類型。
我用 scraper 風格的評分表先做的暫評是 60/100,但這個分數其實是把一個 converter 拿去考 crawler 的試題,分數自然偏低。若回到它自己的主場,它的文字保真度其實很高;真正的弱點是結構面(表格、PDF 標題)與包裝面(體積、import、[all] 陷阱),不是文字品質。把它看成它真正的樣子——檔案轉 Markdown 工具——它就是一個扎實、持續維護、但有幾個鋒利邊角值得你在接上正式環境前先知道的工具。
常見問題
MarkItDown 是網頁爬蟲嗎?
不是。它沒有 crawler、沒有 JavaScript 渲染、沒有跟連結,也不會翻頁。它是把你已經有的檔案與文件——PDF、DOCX、XLSX、PPTX、圖片、HTML——轉成 Markdown。如果你需要抓取並爬行即時網頁,應該用像 Thunderbit 或 Firecrawl 這類工具;MarkItDown 是後面那一步,負責把已抓取或本機的檔案轉成乾淨 Markdown。
為什麼 pip install markitdown[all] 會裝到舊版本?
在 Python 3.14 上,[all] extra 會鎖定 youtube-transcript-api~=1.0.0,但這個範圍內的所有版本都限制 Python 版本必須低於 3.14。resolver 無法滿足這個 pin,只好默默回退到 markitdown 0.0.2,也就是兩年前的版本。解法是先固定版本,再分開裝 extras:pip install 'markitdown==0.1.6',然後再加上 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6'。這件事已在 issue #2179 被追蹤。
MarkItDown 會對掃描 PDF 做 OCR 嗎?
預設安裝不會。它的 PDF 路徑只有文字擷取功能,所以如果 PDF 只有圖片、沒有文字層,輸出就是空字串——沒有錯誤、沒有警告。OCR 需要可選的 Azure Document Intelligence backend 或 plugin,而這些都不會隨預設安裝一起來。這也是一個長期被追蹤的缺口(issue #1268)。
MarkItDown 處理表格的表現如何?
就內容來說非常好——在我測的 13 個案例裡,所有表格內容都 100% 保留下來。結構方面就要看形狀:簡單、寬表、無表頭、空欄位表格都會輸出成乾淨的 GFM grid,但 rowspan 與 colspan 容易變亂(而且 rowspan 可能悄悄把資料對到錯的欄位),巢狀表格會被攤平成亂掉的列,cell 裡的字面 pipe 也不會跳脫。Markdown 的扁平表格格式本來就無法表達 span 或巢狀。
MarkItDown 夠快,能處理大型文件嗎?
它不會在大型檔案上當機,但資源預算要看文件類型。492 頁 PDF 大約花 3.2 分鐘(約 0.39 秒/頁),因為它會逐頁做表單偵測,而且是 CPU-bound。5 萬列的試算表大約一分鐘內完成,但因為會在記憶體中組成一整大段 Markdown,所以峰值會多吃 374 MB RAM。大 PDF 請預留幾分鐘 CPU;大試算表請預留數百 MB 記憶體。
試用 Thunderbit 進行網頁資料擷取 Get Started Free


