多個PDF批次轉Markdown,一次完成

作者 pdftomd.tools 團隊 · 更新於 · 約 6 分鐘閱讀

要一次把多個 PDF 轉成 Markdown,最省事的方法是在批次頁面一口氣選好所有檔案,例如我們的 批次PDF轉Markdown 工具,再下載一個 ZIP。檔案有好幾百個,或是要固定執行的工作,寫一段簡短的 Python 迴圈比較好;版面複雜的,可以用 marker 的資料夾指令。不管選哪一種,轉完都要檢查有沒有空白的結果。

插圖:一疊呈扇形展開的 PDF 檔案流進裝著 Markdown 檔的 ZIP 壓縮檔

依檔案數量挑方法

要用哪種方法,跟 PDF 本身關係不大,主要看有幾個檔案、多久要做一次。大致上:

  • 幾個到幾十個、只做一次:用瀏覽器的批次頁面。什麼都不用裝,檔案也不會離開你的裝置。
  • 好幾百個,或每週都要做:寫個 Python 迴圈跑整個資料夾。可以排程、留紀錄,也能保留資料夾結構。
  • 掃描檔、表單、公式、特殊版面:用 marker 這類以模型為基礎的工具。在一般筆電上會慢很多。它的設計是用 OCR 讀取沒有文字層的頁面,但在我們的 CPU 測試裡,掃描頁還是空白;建議先拿幾個檔案試跑。
插圖:三張卡片上的 PDF 越疊越高,分別交給瀏覽器視窗、終端機和伺服器機櫃處理
量少用瀏覽器,固定工作用腳本,數量龐大或版面困難的交給高規格電腦上的模型工具。

為了公平比較三種方法,我們準備了 20 個檔案、共 40 頁的測試組:十二個表格和版面範例、一份英文指南、一份 11 頁的中文報告、一份頁首重複的 4 頁報告、一張沒有文字層的掃描頁,還有分別放在兩個資料夾、檔名都叫 notes.pdf 的兩個不同檔案。全部都在我們的建置主機(Linux x86_64, 8 vCPU, 16 GB RAM, no GPU)上執行。

在瀏覽器裡批次把 PDF 轉成 Markdown

開始之前,先打開兩三個 PDF,試著反白一句話。可以反白,就代表檔案有文字層,下面每種方法都能用;反白不了,就是掃描檔或圖片,只有 OCR 工具才抓得出文字。先知道手上的檔案混了哪些,可以省掉重跑一次。

打開批次頁面,按「選擇檔案」(或把選好的檔案拖到放置區),一次選取全部 PDF。每個檔案會在分頁裡依序轉換,最後頁面會提供一個 ZIP,每個 PDF 各對應一個 .md。因為是在本機處理,速度取決於你的裝置,而不是上傳速度。如果檔案都在同一台電腦上,這就是批次 PDF 轉 Markdown 最快的方法。

螢幕截圖:在我們的批次頁面一次把多個 PDF 轉成 Markdown,結果清單顯示頁數、表格數和「下載 ZIP」按鈕
20 個檔案的實測截圖:每個檔案一列,標出頁數和表格數。

在我們的測試中,從選檔案到 ZIP 產生,整組檔案在 Chrome 155.0.8059.84 裡大約花了 0.8 秒(跑三次,介於 0.8 到 1.0 秒)。ZIP 裡有 20 個 Markdown 檔。兩個 notes.pdf 分別輸出成 notes.md 和 notes-2.md,沒有互相覆蓋;掃描頁則會在清單裡被標示出來,不會默默失敗。

限制是:瀏覽器本身讀不了資料夾樹狀結構,來自不同資料夾的檔案會並排放在同一個 ZIP 裡;數量非常大時,也會受到分頁記憶體的限制。好幾百個檔案的話,就分幾批選,或改用腳本。

用 pymupdf4llm 寫 Python 迴圈

處理這件事的 Python 腳本只要幾行。下面這支會把整個資料夾的 PDF 轉成 Markdown:逐一走過資料夾,輸出時保留相同的結構(所以兩個 notes 檔會分開),某個檔案失敗也會繼續執行:

import pathlib, pymupdf4llm

src, out = pathlib.Path("pdfs"), pathlib.Path("markdown")
for pdf in sorted(src.rglob("*.pdf")):
    dest = out / pdf.relative_to(src).with_suffix(".md")
    dest.parent.mkdir(parents=True, exist_ok=True)
    try:
        dest.write_text(pymupdf4llm.to_markdown(str(pdf)), encoding="utf-8")
    except Exception as e:
        print(f"skipped {pdf}: {e}")
用 pip install pymupdf4llm 安裝。這個函式庫採 AGPL-3.0 授權,Artifex 另有販售商業授權。

同樣 20 個檔案,迴圈在 5.3 秒內跑完,包含 Python 啟動和匯入函式庫的時間。它寫出 20 個檔案,其中兩個是空的:一個是沒有可讀文字的掃描頁,另一個是表格轉了 90 度的頁面。如果有好幾千個檔案,由於每個檔案彼此獨立,可以把同一個迴圈丟進行程池,每個 CPU 核心一個工作者。表格和頁碼範圍的選項請看我們的 Python 教學;pymupdf4llm 跟另外兩個函式庫的比較,請看 函式庫比較文章。

marker 的資料夾指令

marker 有一個處理整個資料夾的指令:marker /path/to/pdfs --output_dir out。它只讀資料夾的第一層(腳本用 os.listdir 列出檔案),所以我們先把檔案複製到一個平面的資料夾。常用的選項有:平行處理用的 --workers、從中斷處接著跑的 --skip_existing,以及試跑用的 --max_files。

在我們沒有 GPU 的電腦上用預設設定,整個資料夾花了 5 分 51 秒(含載入模型),產出 20 個結果,大約是 Python 迴圈的 66 倍。轉了方向的表格它有救回來,但寫了兩次;掃描頁在這次執行中仍然是空白檔。在有支援 GPU 的電腦上情況會不一樣;用筆電的話,只把真的需要的檔案交給 marker。

檔名、重複名稱與資料夾結構

插圖:兩個資料夾裡各有一個同名檔案,合併到同一個 ZIP 後保留成兩個不同的 Markdown 檔
兩個檔案、同一個名字:ZIP 一定要兩個都留下來。
  • 重複名稱:一次轉很多 PDF 時,要先決定兩個資料夾裡的同名檔案怎麼處理。我們的批次頁面會加上編號;上面的迴圈會保留子資料夾;寫得太陽春的腳本會在沒有警告的情況下蓋掉第一個檔案。
  • 結構:如果資料夾結構有意義(每位客戶或每一年一個資料夾),就把它留住:可以像上面一樣用 relative_to,或每個資料夾各用一次批次頁面。
  • 命名:.md 沿用 PDF 的主檔名,之後就一定找得到原始檔。想要比較好讀的名字,之後再到筆記 App 裡改。
  • 把 Markdown 檔打包成 ZIP 最方便交給別人;如果輸出還要給另一支腳本處理,用資料夾比較好。

品質檢查:找出掃描檔和空白結果

一次把多個 PDF 批次轉 Markdown,很容易漏看單一檔案時一眼就看得出的問題。我們測的每一個工具,都至少產出一個空白或幾乎空白的檔案,而且沒有 OCR 的話,誰都沒辦法把讀不到的頁面變成文字。所以每次大量轉換後,都要找出那些短得不太對勁的檔案:

# Markdown files under 100 bytes are usually scans or image-only pages
find markdown -name '*.md' -size -100c
在輸出資料夾(或解壓縮後的 ZIP)裡執行。
螢幕截圖:批次結果清單中,一個只有圖片的檔案被標上警告,提示它看起來是掃描檔、沒有文字層
螢幕截圖:只有圖片的檔案會在清單中被標示,它的 Markdown 也會寫明沒有可擷取的文字。

接著隨機打開幾個結果,跟 PDF 對照:標題、一個表格、最後一段。如果這些檔案要丟給聊天模型,我們的 最適合 ChatGPT 的檔案格式 一文有說明,為什麼這一步檢查值得做,才能換到乾淨的 Markdown。

20 個檔案的實測時間

同樣 20 個 PDF(40 頁)用三種方法轉換,依我們的測試(2026 年 10 月 19 日,只用 CPU)
方法時間輸出數空白輸出重複名稱
我們的批次頁面(瀏覽器)0.8 秒20scanned-sample.md加上編號(notes、notes-2)
Python 迴圈,pymupdf4llm 1.28.25.3 秒20rotated.md, scanned-sample.md保留在子資料夾
marker 2.0.0 資料夾指令5 分 51 秒20scanned-sample.md只支援平面資料夾(由我們改名)
瀏覽器的時間從選檔案算到 ZIP 產生。Python 和 marker 的時間含啟動時間,marker 另含載入模型。只有一台電腦、一小組樣本,請當作數量級參考。

對多數人來說,結論很簡單:多個 PDF 批次轉 Markdown,先從瀏覽器開始;工作會一再重複,就寫成腳本;其他工具讀不出來的頁面,再交給以模型為基礎的工具。

資料來源

  1. PyMuPDF4LLM (README and licence) — Artifex, GitHub
  2. marker (README, licence and model licence) — Datalab, GitHub
  3. pathlib: Path.rglob — Python documentation
  4. find(1) — GNU findutils manual

常見問題

要怎麼一次把多個 PDF 轉成 Markdown?

在我們這類批次頁面選取所有檔案並下載 ZIP,或寫一段簡短的 Python 迴圈跑整個資料夾。轉完記得檢查有沒有空白的輸出。

批次頁面一次可以選幾個檔案?

沒有固定上限,限制在於瀏覽器的記憶體。我們測試 20 個檔案、40 頁大約花了一秒。好幾百個大型檔案的話,請分批處理或改用腳本。

同名的檔案會怎樣?

我們的批次頁面會替第二個檔案加上編號(notes.md、notes-2.md)。用腳本的話就由你決定:保留子資料夾、加上後綴,或直接略過。

掃描的 PDF 可以批次轉換嗎?

只讀文字層的工具沒辦法:掃描檔會是空白,我們的工具會把它標示出來。你需要先做 OCR。marker 就是為此設計的,但在我們沒有 GPU 的測試中,掃描頁的結果仍是空白;大量轉換前請先抽樣測試。

可以排程批次把 PDF 轉成 MD 嗎?

可以,用腳本就行。把 Python 迴圈放進 cron 或工作排程器,再加上類似 --skip_existing 的邏輯,只轉換新的檔案。

批次頁面會上傳我的檔案嗎?

不會。轉換是在瀏覽器分頁裡完成的,ZIP 也是在你的裝置上產生。