多个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 的文件名,以后总能找到原文件。想要更好读的名字,之后在笔记软件里改。
  • 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 也是在你的设备上生成的。