PDF转Markdown实战:用MinerU 3.4.5搞定扫描件、公式与表格
PDF 转 Markdown看着像是“另存为”就能解决的事真做起来完全是拆盲盒。扫描件没有文字层、公式全部变成图片、表格跨页错位、双栏论文被读成单栏……这些坑我前前后后踩了大半年直到把 MinerU 3.4.5 完整跑通才算找到一个能批量、可靠出活的开源方案。MinerU 是当前文档结构化解析领域热度很高的项目官方命令行入口仍然叫 magic-pdf 系列新的 3.4.5 版本把 PDF 解析成 Markdown 的链路做得非常完整内置版面分析、OCR、公式识别、表格识别、阅读顺序还原一条命令就能把乱七八糟的 PDF 收拾成干净的结构化文本。这篇内容主要写给三类人需要把论文、教材、技术手册批量转成 Markdown 喂给 RAG/知识库的开发者日常做文档整理但不想手动复制粘贴的办公党以及想在自己电脑上部署 MinerU体验“本地解析不求人”的折腾型用户。我会从安装、命令行、模型选型、参数调优、API 封装到常见坑完整过一遍。1. 先把问题说透PDF 转 Markdown 为什么一直是老大难1.1 PDF 的“物理层”和“逻辑层”是两回事PDF 文件本质上不是一本书而是一堆“打印指令”。每个文字、每张图片都被记录成带坐标的对象阅读器只是按照坐标把它们画出来。所以 PDF 里可能根本没有“段落”这个概念更不用提“标题”“表格”“公式”的逻辑结构。我经常用一个比喻PDF 相当于把一页纸拍成照片文字层只是“可选的注释”扫描件则连注释都没有纯粹是一张图。这就是为什么 PDF 转 Markdown 不是“另存为”能搞定的。Markdown 要求你有标题层级、段落顺序、列表、表格、代码块这些信息 PDF 物理层一概不给你。MinerU 这类工具的真正价值是先把页面做版面分析找出哪里是标题、哪里是正文、哪里是图片、哪里是表格然后再按人类阅读顺序重新组织成一个有结构的文档。这个“版面分析 阅读顺序还原”的过程就是行业里说的文档结构化解析。1.2 传统方案都有哪些硬伤我用过很多解析库先说结论没有一个是全能的。PyMuPDF、pdfplumber 这类库擅长抽取文本和坐标但遇到扫描件就无能为力也不认识公式和表格结构。PaddleOCR 能识别文字但输出的是“一堆文字块”不会告诉你哪些文字是标题也不负责把表格整理成 Markdown。marker 和 nougat 在特定领域表现不错但面对中文复杂版面、合并单元格表格时还是容易翻车。用 Adobe Acrobat 直接导出 Markdown/Word 的前提是 PDF 本身带完整的标签结构国内很多网上下载的资料根本不带。MinerU 的思路不太一样。它把自己做成了完整管线检测 → 分类 → 识别 → 排序 → 输出。一套流程下来图片、文本块、文本框之间的关系都保存到 JSON 里最终再渲染成 Markdown。对做知识库的人来说这个中间 JSON 甚至比 Markdown 更值钱因为它保留了版面坐标和元素类型。1.3 从 magic-pdf 到 MinerU 3.4.5版本脉络别搞混很多人第一次接触的是 magic-pdf 这个词后来突然看到 MinerU以为换了项目。其实 MinerU 是项目名magic-pdf 是早期的安装包和命令行名字社区里一直混着叫。我自己最早用的版本是 2.x当时还叫 magic-pdf命令行是magic-pdf -p input.pdf -o output。到了 3.x 之后官方文档重点推mineru命令安装包也变成了mineru[core]但为了兼容很多教程里的 magic-pdf 命令依然能用。这次我重点跑的是 3.4.5。它在 3.x 基础上把模型加载和推理流程又收敛了一遍最直观的感受是首次安装后模型下载更顺输出目录更整洁CPU 跑 OCR 的等待时间比旧版短了一点。如果你已经装了旧版建议先pip install -U mineru[core]升级再用新命令mineru --version确认版本别被网上旧教程的参数带偏。2. 部署与一条命令跑通五分钟先出一份 Markdown2.1 环境准备Python 版本和依赖尽量听话MinerU 对 Python 版本有要求我实测 3.10 是最稳妥的3.11 也能跑但个别依赖需要单独编译。建议先用 conda 或 venv 建一个干净环境不要直接往系统 Python 里装因为 MinerU 会带进大量深度学习依赖容易和你已有的 torch 版本打架。安装命令本身不复杂conda create -n mineru python3.10 -y conda activate mineru pip install -U mineru[core]装完后可以先用mineru --version看一眼版本号确认是 3.4.x 再继续。如果电脑上没有 GPU[core]版本已经能跑如果你之后需要更完整的 OCR 支持也可以安装mineru[full]多出来的是额外模型依赖体积更大CPU 机子慎用。2.2 模型权重从哪里来MinerU 的解析模型不是内置在 pip 包里的第一次运行会自动下载模型权重。权重主要来自开源模型仓库体积加起来大概几个 GB。如果你的网络环境下载很慢可以把下载地址改成可访问的模型仓库来源或者在本地把官方提供的模型目录放到缓存路径下。这里有个小经验别第一次就扔一堆 PDF 进去先用一个小文件跑一遍让模型下载和缓存检查顺利完成再跑大批量。下载过程不顺利时常见报错无非是连接超时或证书问题。检查网络放行、配置相关环境变量指向可用的模型仓库基本能解决。这里不展开原则就是“先让模型落地再谈解析效率”。2.3 最小可用命令一键 PDF 转 Markdown装好环境后真正干活只需要一条命令mineru -p sample.pdf -o output -m auto -d cpu各个参数我的理解-p指定输入 PDF 路径也可以传一个目录MinerU 会批量处理目录下所有 PDF。-o输出目录解析结果会按文件名分文件夹存放。-m auto方法模式auto让程序自己判断页面是否需要 OCR。扫描版页面会自动走 OCR文本型 PDF 直接用文本层速度差距非常大。-d cpu强制使用 CPU。如果机器有 N 卡改成-d cuda会快很多。Mac 的 M 系列芯片可以尝试-d mps。命令跑完后输出目录里能看到的文件大致是这样output/ └── sample/ ├── sample.md ├── images/ └── sample.jsonMarkdown 文件就是最终要做的东西图片目录放着从 PDF 里裁剪出来的插图JSON 则是结构化的中间结果包含每个元素的类型、坐标和内容。2.4 CPU 和 GPU 的取舍别被“快”绑架我自己的主力机是带核显的旧笔记本CPU 跑单篇 20 页论文-m ocr大概需要十几分钟-m auto对扫描版也是全场 OCR慢得让人想放弃。后来换成有独显的机器同样文件只需要一两分钟体验完全不是一个级别。所以如果只是偶尔转几页资料CPU 完全够用但如果你要批量处理几百份 PDF、做知识库强烈建议找一块 8G 以上显存的显卡。实在没有 GPU就分批跑、每个批次文件不要太多同时观察内存占用。这里说的“内存占用”不只是心理安慰——MinerU 会先把模型加载进内存遇到超大 PDF 还会缓存中间结果跑着跑着把 16G 内存吃满的情况我都见过。3. 解析质量的关键版面、公式、表格和图片不能只看热闹3.1 版面和阅读顺序为什么双栏论文总被读乱MinerU 的版面分析模型会把页面分割成多个区域比如标题、正文、图片、表格、公式区。分割只是第一步对这些区域进行排序才是决定 Markdown 顺序的关键。双栏论文的难点在于视觉上从左到右读是“左栏上→左栏下→右栏上→右栏下”但坐标排序很容易排成“左栏上→右栏上→左栏下→右栏下”。3.4.5 在这块有改进但我建议遇到乱序时先看一眼输出的 JSON。JSON 里每个区域会有坐标bbox和类型你可以很快判断是不是排序算法没理解分栏。如果问题比较多可以在调用时把页面旋转、分栏检测相关的模型打开或者采用把页面按列拆开再分别解析的思路。对绝大多数标准论文MinerU 开箱即用的顺序已经不错真正需要人工干预的是左右栏之间带插入框、注释块的复杂版式。3.2 公式识别从图片变成 LaTeX搞科研的人最需要的功能就是公式能输出成 LaTeXMinerU 在这一块做得相当能打。扫描版里的复杂公式比如分数、求和符号、希腊字母基本能还原成 LaTeX 源码公式在 Markdown 里通常以$...$包裹。这里有个实操心得公式后面的标点、上下标和紧跟在公式后的中文偶尔会被识别进公式范围导致 Markdown 渲染异常。遇到这种情况生成的 md 里手动把多出来的部分挪出去即可。MinerU 对公式区域是单独识别的不想转换公式的人可以在配置里关闭公式模型这样能省一部分计算资源。但对于论文党我建议保留因为公式识别是这套工具最值钱的能力之一。3.3 表格识别别指望所有 Excel 级表格都一步到位表格是另一个容易翻车的点。普通的三线表、简单网格表MinerU 能还原成接近 Markdown 表格的样子但带有合并单元格、斜线表头、跨页大表的复杂表格转换后经常会出现行列错乱。我自己的经验是大表格识别成 Markdown 之后最好用支持表格编辑的 Markdown 工具打开检查一遍。如果你只是想把 PDF 里的表格完整提取成 ExcelMinerU 不是最优解它的目标产物是 Markdown 和 JSON不是保留全部单元格属性的 Excel。需要在完整表格数据上做二次加工的话可以从 JSON 里拿表格的坐标再配合表格识别模型单独处理。3.4 图片抽取和中文 OCR 的细节图片抽取做得比较省心插入的插图会单独存到images目录Markdown 里的引用路径默认为相对路径这样整个输出文件夹可以整体移动不会出现图片丢失。如果你计划把 Markdown 发布到博客或导入笔记软件相对路径可能还需要改成本图床地址或绝对路径这是后处理阶段要考虑的。中文 OCR 我是重灾区。普通的印刷体 PDF-m auto配合中文语言模型效果很好但低分辨率的扫描件经常出现“横折撇捺”糊成一片的情况。我的处理优先级是先用工具把扫描页转成更高 DPI 的图片比如 200 DPI 提到 300 DPI再适当做二值化或去底色最后再交给 MinerU。预处理这一步非常影响识别率。如果你在命令行里传了-l ch会让 MinerU 明确按中文语境去识别减少中英文混排时的误判。4. 把 MinerU 变成本地解析服务告别命令行也能批处理4.1 为什么需要本地 API命令行很好用但如果你的项目是一个 Web 应用、或者你希望团队成员打开浏览器就能上传 PDF 转 Markdown就不能每次都登录服务器敲命令。本地 API 意味着把 MinerU 的解析能力封装成 HTTP 接口支持参数传递、任务排队和结果返回。热词里大家关心的“cpu api 的 open appi”本质上就是想在 CPU 机器上跑一个本地服务不需要 GPU 也能让其他程序调用。有人说“可以用现成的在线解析 API”但文档这种东西涉及版权和隐私很多业务根本不敢把 PDF 传到第三方服务。自己部署 MinerU 后数据全程留在本机这是很多人选择本地 API 的根本原因。我自己的知识库项目就是这么干的内网部署一个解析服务各种文档自动化流程统一往这个服务发请求。4.2 一个极简的 FastAPI 封装思路MinerU 本身提供了 Python API但对多数项目来说最不容易出错的封装方式是“FastAPI 子进程调用命令行”。原因很简单命令行参数经过了官方长期测试行为可预期子进程隔离了解析进程崩溃的风险不会因为某个 PDF 把 Web 服务整个带崩。下面是一个极简实现保存成mineru_api.pyfrom fastapi import FastAPI, UploadFile, File from pathlib import Path import subprocess, tempfile, shutil app FastAPI() app.post(/parse) async def parse_pdf(file: UploadFile File(...)): workdir tempfile.mkdtemp() input_path Path(workdir) / input.pdf content await file.read() input_path.write_bytes(content) output_dir Path(workdir) / output cmd [ mineru, -p, str(input_path), -o, str(output_dir), -m, auto, -d, cpu ] subprocess.run(cmd, checkTrue, capture_outputTrue) md_path list(output_dir.rglob(*.md))[0] md_text md_path.read_text(encodingutf-8) shutil.rmtree(workdir) return {markdown: md_text}这个接口接收 PDF 文件返回 Markdown 字符串。你没看错就这么点代码。实际项目里你还需要加鉴权、任务队列、图片回传、错误日志但这些都不影响理解核心调用流程。4.3 并发和排队CPU 机器的现实约束如果是 CPU 机器跑这个 API千万别指望它同时处理十个请求。MinerU 解析 PDF 是一个计算密集的过程CPU 机器上并发开太多任务反而会互相抢资源单个任务速度更慢。我在项目里用的是最简单的方案FastAPI 的接口收到请求后把任务丢进队列一个 worker 一个任务地消费前端轮询结果。这样虽然不能并行但至少不会把内存打爆、不会让服务无响应。调用方式也很直白用curl测试curl -F filesample.pdf http://127.0.0.1:8000/parse返回的 JSON 里就是解析后的 Markdown。把这个接口接到微信机器人、飞书文档、RAG 数据管道都是顺手的事。5. 实战中的高频踩坑记录我踩过的你不用再踩5.1 扫描件识别成乱码怎么办现象整页 PDF 转出来是大量无法阅读的 Unicode 字符或者中文变成了简体/繁体混杂、错字连篇。原因OCR 模型对低分辨率图片的判断不够准确。解决先用 PDF 工具把页面导出成 300 DPI 图片再对图片做去底色、增加对比度最后用-m ocr强制识别。另外确认语言参数是-l ch不要把默认英文模型当成中文模型用。5.2 表格行列错位现象复杂表格变成 Markdown 后单元格数量对不上列数忽多忽少。原因表格线缺失、合并单元格、跨页表被拆开等。解决优先检查原 PDF 是不是扫描件如果表格区域本身是一张图则识别难度更高。可以先把表格区域裁出来单独放大再做识别MinerU 解析完的 JSON 里有表格的行列信息比起 Markdown 更接近原始结构可以基于 JSON 做修复。5.3 图片路径失效现象Markdown 里的图片引用打不开或者别人拿到目录后图片全丢。原因相对路径在移动文件后失效或者图片文件夹被遗漏。解决保持images目录和 Markdown 文件的相对关系如果要分发给别人我会把整个输出目录打成压缩包。发布到在线平台前根据目标平台要求替换图片为绝对路径或图床链接。5.4 单文件解析失败导致批处理中断现象批量目录里有几十个 PDF跑到第 5 个报错后面的全停。原因某些 PDF 页面畸形、加密、或模型识别异常导致后台进程退出。解决不要依赖一条命令无脑批处理。写脚本时对每个文件单独调用 MinerU捕获异常后继续处理下一个。这样单个文件失败不会拖垮整个任务。我习惯把处理失败的文件名记到日志里跑完统一检查。5.5 常见问题速查表现象可能原因排查/解决思路输出全是乱码中文语言参数没设置加-l ch确认模型下载完整CPU 跑得特别慢OCR 量大用-m auto减少无用 OCR或换 GPU表格错位复杂表格结构从 JSON 提取表格坐标二次处理命令找不到mineru环境没激活/安装未完成pip list检查确认虚拟环境已激活模型下载卡住网络问题配置可访问的模型仓库来源换个时间再试页面被裁掉图片预处理过度避免过度二值化保留原灰度信息写在最后的个人体会我用 MinerU 处理过的 PDF 加起来至少上千页从学术论文、技术手册到扫描版旧书都有。整体感受是它对“版式工整、清晰度正常”的 PDF 表现最好对扫描件需要在预处理上多花心思。不要幻想有一款工具能 100% 还原所有复杂版面MinerU 已经能把 80% 的脏活累活干掉剩下 20% 靠人工检查和工具链配合。最后再分享一个小技巧如果你后续要做 RAG别只存 Markdown把 MinerU 生成的 JSON 一起保存。JSON 里有每个标题、段落、表格、图片的坐标和类型做向量检索时可以把同一页的元素按位置关系拼接成更合理的片段用这种方式喂给大模型的回答质量往往比直接截断 Markdown 更好。这个习惯我坚持了半年收益很大建议你上手之后也试一试。