在與 markitdown 共享的四個 HTML 測試檔中,markdownify 依照我們的計數器產生了相同數量的 Markdown 表格列輸出——36 對 36——而且成功保留了全部 16 個檢查內容字串。它的輸出為 21,062 個 token,名義上最低;不過前三個轉換器彼此差距都在 1.3% 以內。它安裝後佔用 1.8 MiB,採 MIT 授權,在截圖當下有 2,235 個 GitHub stars。
它是這個類別裡討論最少的函式庫,但就這些數據來看,也是我最願意優先採用的一個。
什麼是 markdownify
markdownify 是一個建立在 BeautifulSoup 之上的 Python HTML 轉 Markdown 轉換器。架構就這麼單純:用 BeautifulSoup 解析、遍歷樹狀結構、輸出 Markdown。測試版本:1.2.3,MIT 授權,2,235 stars,42 個未解決 issue,最近一次發布是 2026-06-30——維護仍然很活躍,共有 44 次版本發佈。
官方參考:python-markdownify 的官方倉庫。

它的 API 只有一個函式:
from markdownify import markdownify
md = markdownify(html)
如果你想自訂元素處理,也可以使用類別形式(MarkdownConverter),而且還有一組不錯的選項——標題樣式、項目符號字元、程式碼語言偵測、元素剔除等等。不過最常見的情境還是一行就能搞定,而且確實好用。
執行 pip install markdownify 會拉入 5 個套件與 1.8 MiB,冷啟動匯入只要 0.046 秒——在我測試的三個轉換器中是最快的。它的依賴樹主要就是 BeautifulSoup 以及常見的搭配套件,而很多 Python 專案本來就已經帶著這些套件,所以邊際成本往往幾乎等於零。
測量方式
我用的是這組基底裡另一份測試包先前已用於 markitdown 的四個 HTML 測試檔,並搭配該測試包的預先註冊探針字串——共 16 個精確的正文字串,用來確認是否完整保留,外加頁面外框(chrome)相關的樣板檢查。第五個測試檔 Nothing but tables 是另一個以表格為主的診斷案例,不納入下面這四檔的總表。
| 轉換器 | 正文探針 | 輸出字元數 | Token(o200k) | Markdown 表格列 | 連結數 |
|---|---|---|---|---|---|
| markdownify | 16/16 | 76,868 | 21,062 | 36 | 599 |
| html2text | 16/16 | 76,452 | 21,176 | 32 | 545 |
| markitdown | 16/16 | 76,995 | 21,336 | 36 | 598 |
| turndown | 16/16 | 95,188 | 26,236 | 0 | 611 |
fourway-scores.json。四個測試檔,Token 使用 o200k_base 計算,表格列則以同一套規則在四個檔案上統一計數——包括重新計算 markitdown 已儲存的輸出,結果與其公開數字完全一致。
有三件事特別值得注意。
它在表格列輸出數上與 markitdown 打平。 在四個共享測試檔上,兩者都得到 36 列,而且是用同一種 heuristics 計算。這不代表逐格完全一致;它只表示這兩份輸出在這個計數器下,呈現出相同數量可辨識的 Markdown 表格列。
它的 token 數最低。 21,062,略低於 html2text 的 21,176 與 markitdown 的 21,336,也比 turndown 的 26,236 少了 19.7%。前三者彼此差距只有 1.3% 以內,我會把它視為打平而不是勝出;真正拉開差距的是 turndown。
所有內容探針都保住了。 16 個全數通過。其他三個轉換器也一樣——內容保留並不是這些函式庫之間主要的分水嶺。
它最擅長的表格
冰球統計資料這個測試檔最能區分各轉換器。markdownify:
| Team Name | Year | Wins | Losses | OT Losses | Win % | ... |
| --- | --- | --- | --- | --- | --- | --- |
| Boston Bruins | 1990 | 44 | 24 | | 0.55 | ... |
它使用標準 GFM 格式,包含前後管線符號、分隔列,以及——注意 24 和 0.55 之間那個空白儲存格——它會把空格保留下來,而不是直接略過。這看起來像小事,但其實不是:如果轉換器把空儲存格丟掉,後面每個值都會整欄位移,輸出看起來仍然像是一個正常表格。

turndown 在同樣的輸入下,會把每個值都拆成獨立段落,完全沒有欄位結構。html2text 則會輸出另一種風格的正確表格,但不使用外層管線。
如果 Markdown 要送進模型,正是這些管線與被保留的空儲存格,才能讓它回答「Boston 輸了幾場」這種問題,而不是只能亂猜。
它比 turndown 多做、而且更好的兩件事
表格保真度是最顯眼的差異,但這一點更重要,而且幾乎沒人提。
markdownify 會移除 <script> 和 <style> 內容;turndown 不會。用只會出現在這兩種元素內的標記來計數時,markdownify 在整批測試檔中的輸出帶有0 個 script 標記與 0 個 style 標記;turndown 則分別帶有10 個與 84 個。在 Wikipedia 測試檔上,這差異就是 59,561 個字元對上 74,939 個字元——而且 MediaWiki 內嵌的 JavaScript 設定與 CSS 共 8 行,就佔了 14,644 個字元,也就是那段差距的 95%(script-style-stripping.json)。
對任何要餵給模型的內容來說,這大概是整個比較裡最昂貴的浪費:一大段 JavaScript 設定只會耗 token,卻完全不提供資訊。markdownify 會自動把它去掉,甚至不用特別要求。html2text 也是如此。
以單一測試檔來看,markdownify 與 html2text 在結構簡單時結果完全一致,而在結構複雜時就開始分歧:
| 測試檔 | markdownify | html2text |
|---|---|---|
| Hockey statistics | 27 列 | 27 列 |
| Wikipedia | 9 列 | 5 列 |
| Nothing but tables(獨立診斷) | 62 列 | 59 列 |
在兩個診斷比較裡,markdownify 都產生了更多可辨識的列。特別是在 Wikipedia 測試檔上,依照這個計數器它保留了 9 列,而 html2text 只有 5 列。這是一個提醒:在選擇工具前,應該先用代表性的巢狀與不規則表格實測;但這不代表每個輸出的儲存格語意都一定正確。
安裝與授權,和其他替代方案放在一起看
| 函式庫 | 套件數 | 磁碟佔用 | 冷啟動匯入 | 授權 | Stars | 最近一次發布 |
|---|---|---|---|---|---|---|
| markdownify | 5 | 1.8 MiB | 0.046 秒 | MIT | 2,235 | 2026-06-30 |
| html2text | 1 | 0.2 MiB | 0.077 秒 | GPL-3.0-or-later | 2,168 | 2025-04-15 |
| turndown | 3(npm) | 8.8 MiB | 0.056 秒 | MIT | 11,386 | 2026-04-03 |
官方參考:PyPI 上的 markdownify。
install-and-import.json 與 metadata-snapshot.json。每個函式庫都安裝在自己獨立的空環境中。
html2text 在磁碟上的體積只有它的九分之一,而且採用 GPL-3.0-or-later。如果你做的是可散佈產品,這點請交給負責授權的人先確認;本文不構成法律建議。markdownify 是 MIT,通常更寬鬆,但仍應納入一般合規審查。
如果你的專案本來就已經用了 BeautifulSoup,那 1.8 MiB 其實有點名義化——很多 Python 抓取專案本來就有這個依賴,這時 markdownify 的額外成本幾乎等於零。
在這三者之中,markdownify 的更新節奏也最健康:共有 44 次版本發佈,而且在測試前六週還有一次更新;相較之下,html2text 上一次發布還停留在 2025 年 4 月。
一行 Python 到底能幫你做什麼
整個函式庫就是 markdownify(html),而且很值得明講這個呼叫會替你決定什麼,因為這份比較有三個重點,剛好都跟這些決策有關。
它用 BeautifulSoup 解析,會在不需提示的情況下移除 <script> 與 <style>,並且輸出帶有外層管線與保留空儲存格的 GFM 風格表格。單靠解析器的血統並不能保證它在壞掉的輸入上表現如何,所以這個問題我在下面另外測了。
這些都不是你要額外設定的選項。這就是預設行為;而在 turndown 預設會保留 JavaScript、html2text 預設會在 78 個字元處強制換行的這個類別裡,一個開箱即用、幾乎不需要修正的函式庫,本身就很有價值。
當你需要時,選項也都有:heading_style、bullets、code_language、strip 與 convert 可用於元素允許與拒絕清單,而 MarkdownConverter 則能做逐元素覆寫。這裡所有測量都沒有動用這些選項。
記憶體,以及損壞的 HTML 會怎麼影響它

更大的壓力測試背景,請看十個函式庫的記憶體與不完整 HTML 比較。
這一批評測裡每篇都列為未測、現在補測的兩件事:
峰值常駐記憶體,使用 /usr/bin/time -l,每個測試項目都開一個全新程序——匯入底線代表函式庫載入且閒置時的成本,峰值則包含文件本身。
| 函式庫 | 執行環境 | 匯入底線 | 226 KB 峰值 | 10 MB 峰值 |
|---|---|---|---|---|
| html2text | python3.14 | 18.7 | 19.9 | 71.2 |
| pyquery | python3.14 | 30.3 | 33.9 | 172.5 |
| resiliparse | python3.14 | 20.5 | 25.1 | 225.1 |
| markdownify | python3.14 | 23.9 | 28.9 | 278.5 |
| goose3 | python3.14 | 44.1 | 52.4 | 398.5 |
| cheerio | node22 | 66.8 | 76.5 | 398.5 |
| justext | python3.14 | 30.3 | 36.6 | 431.2 |
| newspaper4k | python3.14 | 52.6 | 61.8 | 668.5 |
| trafilatura | python3.14 | 52.5 | 64.8 | 927.1 |
| turndown | node22 | 47.8 | 68.4 | 2947.1 |
memory-results.json。Python 與 Node 的基準不能直接互相比;兩者的直譯器都算在裡面。
markdownify 落在中間:匯入底線是 23.9 MiB,10 MB 文件時峰值是 278.5 MiB。這是 html2text 峰值的 3.9 倍,大約是 turndown 的十分之一;這就是它底層採用 BeautifulSoup 的代價。
損壞的 HTML。 十二個文件各自只破壞一件事——未關閉標籤、巢狀錯誤的行內元素、帶空格卻未加引號的屬性、殘留的關閉標籤、根本沒有 <html>、重複屬性、文件在標籤中間被截斷、錯誤實體、未關閉的 <script>、宣稱不實的 charset、包含標記語法的註解、以及 600 層巢狀——再加上 兩個同尺寸的良好格式控制檔,因為「它什麼都沒回傳」只有在函式庫對同大小的乾淨文件也一樣沉默時,才能說明它對 malformed 輸入的處理。
markdownify 在 14 個測試中有 1 個拋出例外,0 個回傳空內容,並在損壞檔案中成功恢復 30/33 個哨兵字串(malformed-results.json)。其中有一個測試檔不納入這個統計:依照 HTML5 規範,未關閉 <script> 之後的內容全部都算 script 內容,所以在那個案例中丟失那些內容是正確行為,若成功還原反而才是偏差。
優缺點
優點。 依同一規則計算時,表格保真度與 markitdown 打平。四者之中 token 數最低。MIT。1.8 MiB;如果你的專案裡已經有 BeautifulSoup,邊際成本幾乎是零。冷啟動匯入速度最快,只有 0.046 秒。持續更新。能保留空白表格儲存格。可透過 MarkdownConverter 逐元素覆寫轉換行為。直接用單行函式呼叫就對了。
缺點。 它依賴 BeautifulSoup,所以如果你本來沒有這個套件,磁碟佔用會比 html2text 大九倍。2,235 stars 代表社群規模比 turndown 小——遇到怪問題時可參考的實作範例也比較少。只支援 Python,所以在 Node 技術棧裡幫不上忙。還有 42 個未解決 issue。
誰該用,誰不該用
如果你是 Python 工作負載,而且輸入長得像這些測試檔,先從 markdownify 開始。 它在這個計數器下與 markitdown 的表格列輸出數打平,token 數又處於最低群組,而且是 MIT 授權。如果你本來就依賴 BeautifulSoup,它的額外安裝成本可能很小;不過還是要在你的環境中實際確認依賴差異。
如果你的依賴預算是以幾百 KB 計算,且它的輸出樣式適合你的頁面,可以考慮 html2text。 但在散佈前,請先和負責授權的人一起檢視 GPL-3.0-or-later 的影響。
如果你本來就在轉 PDF 或 Office 文件,可以考慮 markitdown。 這裡它們的 HTML 結果在表格列輸出數上相同,但更廣泛的保真度並沒有被證明等價。
如果你在 Node 環境,就跳過它。 這時 turndown 才是自然答案——不過要搭配 turndown-plugin-gfm 一起裝,因為 turndown 核心本身完全不會產生表格。
受管理 API 的位置
markdownify 只會轉換你已經拿到手的 HTML。它不負責抓取、不渲染 JavaScript,也不處理反機器人防護——這四個轉換器都不做,而在許多真實目標網站上,這其實才是更難的那一半。
若要看同樣四個測試檔在全部五個轉換器中的表現,請參考五向 HTML 轉 Markdown 比較。
我們在 Thunderbit 的開發者工具鏈,處理的是前段那個更上游的工作:POST /distill 會抓取網址並回傳 Markdown,而 POST /extract 會回傳結構化 JSON。兩者都可透過 MCP 伺服器與 CLI 使用;價格請見 Thunderbit 定價頁。這些雲端端點並未與本次本地轉換器做基準測試,所以這是類別差異,不是效能比較。
更誠實的說法是:如果 HTML 已經在你手上,而且你只想要 Markdown,markdownify 幾乎免費,而且做得跟這裡任何工具一樣好。若你要先抓頁面,或者你要的是結構化欄位而不是敘述內容,那就是另一種採購決策了。
如果你想看更完整的工具地圖,我們的網頁爬蟲 API 總整理涵蓋代管選項,而開源爬蟲主題頁則整理了自架方案。Python 中將 HTML 轉成 Markdown 則是實作導讀。
要不要用 markdownify?
如果你在 Python 環境,而且輸入內容像這些測試檔,markdownify 是很強的候選;但在把它設成預設前,還是先拿你自己的表格與不完整頁面實測。
它在表格列輸出數上與 markitdown 打平,落在 token 最低群組,這次測試的冷啟動匯入速度也是最快,而且是 MIT。相對地,它比 html2text 更耗記憶體,只支援 Python,且在一個 malformed 輸入測試檔上拋錯。磁碟佔用與授權也是選型因素,但不是全部理由。
真正讓我驚訝的是 stars 數。turndown 的關注度高出五倍,但開箱即用時,卻無法正確轉出 markdownify 能處理好的那些表格。在這個類別裡,人氣並沒有反映實測表現;這也正是為什麼這次比較值得做。
試試 Thunderbit 進行網頁資料擷取 Get Started Free
常見問題
markdownify 在 HTML 上真的跟 markitdown 一樣好嗎? 在這四個測試檔中,兩者都輸出了 36 列可辨識的 Markdown 表格列,保留了全部 16 個檢查字串,而且字元數差異在 0.2% 以內。這不能代表逐格或渲染結果完全一致。markitdown 另外還支援 PDF 與 Office 格式,所以這裡只比較量測到的 HTML 輸出。
它需要 BeautifulSoup 嗎? 需要——這就是它的解析器,也是那 1.8 MiB 的主要來源。如果你的專案本來就有 BeautifulSoup,markdownify 的邊際成本就很小;如果沒有,而且磁碟真的很重要,html2text 只有 0.2 MiB 與一個套件,但代價是 GPL-3.0-or-later 授權。
它怎麼處理空白表格儲存格? 它會保留。對於有缺值的測試檔,輸出會把空儲存格維持在原位,所以後續所有值都還在正確欄位。會跳過空儲存格的轉換器,會產生一個看起來仍然正常、但每個值都往左錯一欄的表格;這是更糟的失敗,因為你根本看不出來。
我該用函式還是類別?
一般情況用 markdownify() 函式。只有當你需要覆寫特定元素的轉換方式時,才用 MarkdownConverter——這裡所有測試都只用了預設選項的函式版本。
這裡哪些沒有測? 四個共享測試檔再加一個純表格診斷,並不能代表完整語料。另行測試的 malformed 套件涵蓋了 12 種已命名的破壞情況與 2 個控制檔,但並未涵蓋所有壞掉的 HTML 形式。巢狀清單、定義清單、註腳、數學、Markdown 與 HTML 互轉、逐格表格等價性、以及各種設定變體都沒有比較;轉換速度也沒有比較。


