多个PDF批量转Markdown,一次搞定
作者 pdftomd.tools 团队 · 更新于 · 阅读约 6 分钟
要把多个 PDF 批量转成 Markdown,最简单的是在批量页面一次选中所有文件,比如我们的 批量PDF转Markdown 工具,然后下载一个 ZIP。文件有几百个、或者要定期跑,写个简短的 Python 循环更合适;版式复杂的,可以用 marker 的文件夹命令。不管用哪种,转完都要检查有没有空白的结果。

按文件数量选方法
选哪种方法,主要不看 PDF 本身,而看有多少个、多久做一次。大致是这样:
- 几个到几十个,只做一次:用浏览器里的批量页面。不用安装任何东西,文件也不离开你的设备。
- 几百个,或者每周都要做:写个 Python 循环遍历文件夹。可以定时运行、记日志,还能保留目录结构。
- 扫描件、表单、公式、特殊版式:用 marker 这类基于模型的工具。在普通笔记本上会慢很多。它本来是为了用 OCR 读没有文字层的页面,但在我们的 CPU 测试里,扫描页依然是空的;最好先拿几个文件试试。

为了公平比较三种方法,我们准备了 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 最快的办法。

在我们的测试里,从选文件到 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}")同样 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。
文件名、重名和目录结构

- 重名:一次转很多 PDF 时,要想好两个文件夹里的同名文件怎么处理。我们的批量页面会加编号;上面的循环保留子文件夹;写得粗糙的脚本会不声不响地覆盖第一个文件。
- 目录结构:如果文件夹本身有含义(每个客户或每年一个文件夹),就保留它:要么像上面那样用
relative_to,要么每个文件夹单独用一次批量页面。 - 命名:
.md沿用 PDF 的文件名,以后总能找到原文件。想要更好读的名字,之后在笔记软件里改。 - Markdown 文件打包成 ZIP 最方便转给别人;如果输出还要交给另一个脚本,用文件夹更好。
质量检查:找出扫描件和空白结果
多个 PDF 批量转 Markdown 时,单个文件一眼就能看出的问题很容易被漏掉。我们测试的每个工具都至少产出了一个空文件或几乎为空的文件,而且没有 OCR,谁都没法把读不出来的页面变成文字。所以每次大批量跑完,都要找出那些短得不正常的文件:
# Markdown files under 100 bytes are usually scans or image-only pages
find markdown -name '*.md' -size -100c
然后随机打开几个结果,和 PDF 对照:标题、一张表格、最后一段。如果这些文件要交给聊天模型,我们那篇 ChatGPT 最适合的文件格式 解释了为什么这一步检查值得做,能换来干净的 Markdown。
20 个文件的实测耗时
| 方法 | 耗时 | 输出数 | 空白输出 | 重名处理 |
|---|---|---|---|---|
| 我们的批量页面(浏览器) | 0.8 秒 | 20 | scanned-sample.md | 加编号(notes、notes-2) |
| Python 循环,pymupdf4llm 1.28.2 | 5.3 秒 | 20 | rotated.md, scanned-sample.md | 保留在子文件夹里 |
| marker 2.0.0 文件夹命令 | 5 分 51 秒 | 20 | scanned-sample.md | 只支持平铺文件夹(由我们改名) |
对大多数人来说,结论很简单:多个 PDF 批量转 Markdown,先用浏览器;任务要反复做,就写成脚本;其他工具读不了的页面,再交给基于模型的工具。
参考来源
- PyMuPDF4LLM (README and licence) — Artifex, GitHub
- marker (README, licence and model licence) — Datalab, GitHub
- pathlib: Path.rglob — Python documentation
- 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 也是在你的设备上生成的。

