MinerU 本地文档解析实战:PDF/扫描件/复杂排版,RAG 数据准备神器
我之前在多篇 RAG 文章里反复提一句话:”RAG 80% 的效果不在模型,在你给它的数据“。今天就把数据这一环最关键的”PDF 解析”专门写一篇。
起因是上周一个读者发来求助:
“知识库搭好了,模型也换成 BGE-M3,但客户给的合同 PDF 永远问不出来——明明合同里有这条规定,检索就是召不出来。”
我让他把那份 PDF 发我一份,打开一看:双栏排版 + 大量表格 + 部分扫描件页。再去看他知识库里的 chunk,全是乱码和半句话。问题压根不在 RAG,是 PDF 在喂模型之前就已经废了。
今天讲的 MinerU 就是解决这个问题的。上海 AI Lab 开源、GitHub 25K+ star,2026 年 RAG 数据准备链路里几乎绕不开。
一、为什么 PyPDF/pdfplumber不够
很多人 RAG 入门用 PyPDF2.extract_text():
import PyPDF2text = PyPDF2.PdfReader("contract.pdf").pages[0].extract_text()
这种方案能搞定的只有”一栏 + 纯文字 + 矢量 PDF”。一旦遇到:
-
双栏 / 三栏排版:文字顺序错乱,左栏第一行接右栏第一行 -
表格:完全丢失结构,变成挨着的一串数字 -
公式:完全识别不出来 -
扫描件 PDF:根本就是图像,提不出任何文字 -
页眉页脚混入正文:每页都重复出现”第 X 章 / 版权所有”污染上下文 -
图片中的文字:完全识别不出 -
PDF 嵌入字体编码异常:变成 ???或乱码
这些不是 RAG 模型能修的,是数据源头烂了。
二、MinerU 干什么
MinerU 是个全流程文档解析工具链,把上面这些痛点全部处理掉:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
简单说:输入 PDF,输出 Markdown——结构清楚、表格保留、扫描件 OCR、公式转 LaTeX。
三、安装:用 Docker 跑最省事
MinerU 依赖一堆模型和 GPU 驱动,强烈推荐 Docker 部署,避免环境地狱:
docker pull opendatalab/mineru:latestdocker run -d --gpus all \ -p 8888:8888 \ -v ~/mineru_data:/data \ --name mineru \ opendatalab/mineru:latest
首次启动会下载 8GB 左右的模型文件,国内网络慢的话设镜像源。
不愿用 Docker 的直接 pip:
pip install -U "magic-pdf[full]"
但要装 paddleocr、paddle、torch、若干 CV 依赖,环境冲突概率高。
四、第一次解析
最简单的命令行:
magic-pdf -p contract.pdf -o output/
输出目录长这样:
output/contract/├── auto/│ ├── contract.md # 主输出:清洁 Markdown│ ├── contract.json # 结构化 JSON(带 bbox)│ ├── contract_layout.pdf # 可视化:版面识别结果│ ├── contract_content_list.json # 内容块列表│ └── images/ # 提取的图片
打开 contract.md,你会看到:
# 合同名称## 第一章 总则第一条 本合同由甲方 XX 公司与乙方 YY 公司于...| 货物名称 | 规格 | 单价 | 数量 ||---------|------|------|------|| 设备 A | XXX | 1000 | 5 || 设备 B | YYY | 2000 | 3 |第二条 ...
这才是能喂给 RAG 的内容。表格保留、章节结构清晰、阅读顺序正确。
五、对照实测:同一份 PDF,三种解析器
我用一份 80 页的产品合同(双栏 + 30 个表格 + 5 个公式 + 部分扫描页)做对比:
|
|
|
|
|
|
|
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| MinerU | 97% | ⭐⭐⭐⭐⭐ 完整 markdown | ⭐⭐⭐⭐ OCR | ⭐⭐⭐⭐⭐ |
|
用 MinerU 解析后再喂 RAG:那份合同的检索召回率从 41% → 86%。没换 embedding 模型、没改 chunk 策略,只换了数据预处理这一环。
六、扫描件 PDF 实测
很多客户合同、政府文件、老资料都是扫描件。我测了一份 100 页扫描合同(每页都是图像):
magic-pdf -p scan_contract.pdf -o output/ --method ocr
加 --method ocr 强制走 OCR 流程。
实测:
-
耗时:4060 上 100 页大约 8 分钟(CPU 跑要 30+ 分钟) -
准确率:清晰扫描件 96%,模糊件 82% -
章节识别:能识别”第一章 / 第二章”层级,转成对应 markdown 标题
比商用扫描件 OCR 软件性价比高得多,关键是数据完全本地,合同隐私不出门。
七、表格识别效果
表格是 PDF 解析的硬骨头。我专门测了 20 个不同结构的表格:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
规则表格基本无失误。合并单元格和跨页表格需要事后人工抽查。
八、公式识别
公式被识别为 LaTeX,可以直接在 Markdown 里渲染:
质量守恒方程:$$\frac{\partial \rho}{\partial t} + \nabla \cdot (\rho \mathbf{v}) = 0$$
学术论文、技术规范、工程标准的 PDF 这块刚需。MinerU 集成的 UniMERNet 公式识别准确率 90%+,比直接 OCR 抓出来的乱码强 10 倍。
九、集成进 RAG 流水线
把 MinerU 嵌入到 RAG 数据预处理:
import subprocessfrom pathlib import Pathdefparse_pdf_with_mineru(pdf_path: str, output_dir: str) -> str: subprocess.run(["magic-pdf", "-p", pdf_path, "-o", output_dir ], check=True) md_path = Path(output_dir) / Path(pdf_path).stem / "auto" / f"{Path(pdf_path).stem}.md"return md_path.read_text(encoding="utf-8")# 接进你已有的 RAG 流水线md_content = parse_pdf_with_mineru("contract.pdf", "output/")chunks = split_markdown(md_content, chunk_size=500)embeddings = embed_chunks(chunks)store_to_vector_db(chunks, embeddings)
关键改动:split 时按 Markdown 标题层级切,而不是按字符数硬切。MinerU 输出的 Markdown 已经带了清晰章节结构,按 ##### 切自然形成语义完整的 chunk。
十、性能 / 资源
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
显存峰值约 4GB(OCR + 版面 + 表格模型加载)。和 Ollama qwen3.5:9b 共显存的话,先解析完再启 Ollama 就 OK。
十一、几个实际场景
场景 1:合同 / 法律文件库
律所、法务团队的痛点。MinerU 解析后扔进 RAG,”违约条款怎么约定”秒查。全程本地,客户隐私零外泄。
场景 2:学术论文 / 研究资料
公式 + 多栏排版 + 图表的典型场景。MinerU + Qwen3.5:9b RAG 组合,构建个人科研知识库。
场景 3:扫描件历史档案
档案数字化项目刚需。一台 4060 笔记本一天能跑 1000 页扫描件转结构化数据。
场景 4:财报 / 监管文件
表格密集型场景。MinerU 表格识别后的 Markdown 可以直接喂分析模型问”营收同比变化”这种问题。
十二、行动建议
-
✅ RAG 效果不好的项目:先 review 一下 PDF 解析这一环,往往一换全好 -
✅ 合同 / 法律 / 学术场景:MinerU 是当前最好的本地选择 -
✅ 扫描件 OCR 需求:本地方案首选 -
❌ 纯文字简单 PDF:用 pdfplumber 就够了,MinerU 杀鸡用牛刀 -
❌ 没独显的轻薄本:CPU 模式能跑但慢,体感差
夜雨聆风