169 lines
9.1 KiB
Markdown
169 lines
9.1 KiB
Markdown
---
|
||
title: "为什么越来越多人用 MinerU?"
|
||
source: "https://mp.weixin.qq.com/s/dDW3KUNFkBf-o8yy-yjQYg"
|
||
author:
|
||
- "[[鹏磊]]"
|
||
published:
|
||
created: 2026-10-21
|
||
description:
|
||
tags:
|
||
- "clippings"
|
||
---
|
||
鹏磊 架构师专栏 *2026年10月21日 11:13*
|
||
|
||

|
||
|
||
质保 30 天不掉订阅,掉订阅,按天退差价
|
||
|
||
MinerU 是上海 AI 实验室 OpenDataLab 团队开源的一款文档解析软件,做的事儿很简单:就是把 PDF、扫描件、图片、Office 文档等转换为 Markdown 和结构化的 JSON,并且直接输入到 RAG、知识库或者自己设计的清洗流程中去。目前 GitHub 上已经有 8.2 万个 star,这样的数量级,在文档解析项目中是很少见的
|
||
|
||
和 pdfplumber 那样只提取文本内容不是一回事。公式输出为 LaTeX 格式,表格输出为 HTML 格式,标题、图片、页脚都有相应的类型和坐标信息,该模型可以全部下载到本地运行,在不离开内网的情况下也可以进行数据处理
|
||
|
||
上个月为一家做 RAG 的公司清理标书,有 2000 多个 PDF 文件,双栏、跨页表格以及 LaTeX 公式一应俱全。第一版使用了 pdfplumber 来提取文本内容,但是由于读取顺序被打乱,所以表格变成了一个只有一列数字的表格。换作使用 MinerU 运行一晚上的时候,在第二天 structured\_content.json 文件中就会看到表格已经变成了 HTML、公式也变成了 LaTeX,并且标题层次依然存在。那会儿我就明白了它为什么会传播得那么快
|
||
|
||
## 它所要解决的问题并不是抽离出文字来,而是要把版面还原出来
|
||
|
||
传统库只能根据字符坐标的大小来判断数据之间的关系,并不能够理解到语义。双栏论文按照行来阅读就会出现串栏的情况,页眉、页脚混入到正文中去,表格没有行列之间的关系,在进行扫描之后也无法得到任何信息
|
||
|
||
MinerU 的做法是把每一页的 PDF 渲染成图片,然后进行版面检测,把标题、正文、表格、图片、公式、页眉页脚等都分离开来,并按照阅读顺序重新排列。表格走结构识别输出 HTML,公式走识别模型输出 LaTeX,扫描件再叠一层 OCR
|
||
|
||
该链条在 4.0 的时候被分成四个等级,并且质量、价格都可以自己选择
|
||
|
||
| 档位 | 实际跑什么 | 典型用途 |
|
||
| --- | --- | --- |
|
||
| flash | 原生文本解析 + Flash OCR | 建索引、预览、Office 文档 |
|
||
| basic | ONNX 或 Torch 小模型 | 纯 CPU、扫描件、公式表格 |
|
||
| standard | 小模型 + 1.2B VLM | 复杂版面,默认档 |
|
||
| advanced | 同模型,更多推理计算 | 高价值文档 |
|
||
|
||
标准档背后是 MinerU2.5-Pro-2605-1.2B。模型不大,但是它被用来对文档进行解析的任务上训练过的,并不是用一般的多模态通用模型来套用的。我认为最核心的是专用的小模型,在版面中更加稳定,而且显存可以节省很多
|
||
|
||
## 命令行三分钟跑通
|
||
|
||
4.0 安装包和 2.x 完全不相干,请不要再按照老教程来安装 core、pipeline 等 extra,已经全部失效
|
||
|
||
```
|
||
# 基础包:ONNX + llama.cpp,CPU 和 Apple Silicon 够用
|
||
uv pip install -U "mineru>=4.0,<5"
|
||
|
||
# 有 NVIDIA 卡、要高吞吐再上 full,Linux 会自动装 vLLM
|
||
uv pip install -U "mineru[full]>=4.0,<5"
|
||
|
||
# 国内网络先把模型源切到 ModelScope,否则首次下载模型能卡到怀疑人生
|
||
export MINERU_MODEL_SOURCE=modelscope
|
||
```
|
||
|
||
安装完毕之后使用 `mineru-kit models show` 来查看一下实际生效后的后端情况,否则你会认为自己是在运行 GPU,实际上却一直在消耗 CPU。解析命令有两处入口,行为不同。 `mineru-kit parse` 是无状态的,默认情况下会把整个文档解析出来; `mineru parse` 是一个文档库客户端,PDF 默认只读前 10 页
|
||
|
||
```
|
||
# 单文件转Markdown,standard档:小模型+VLM
|
||
mineru-kit parse paper.pdf -o paper.md --tier standard
|
||
|
||
# 批量目录出 zip;显式 --pages all,绕开两个入口的默认值差异
|
||
mineru-kit parse ./docs -o ./out --format zip --pages all
|
||
|
||
# 只是入库检索,flash 档不跑 VLM,速度快一个量级
|
||
mineru-kit parse manual.pdf -o manual.md --tier flash
|
||
```
|
||
|
||
## 代码中如何连接
|
||
|
||
从 Python 语言的角度来看,4.0 版本把无状态入口收进了 mineru.parser 里面,并且 parse、parse\_async 都是对外开放的
|
||
|
||
```
|
||
from pathlib import Path
|
||
from mineru.parser import parse
|
||
|
||
# tier 决定了成本:flash 走原生文本,standard 才拉小模型加 VLM
|
||
result = parse(
|
||
"paper.pdf",
|
||
tier="standard",
|
||
ocr_mode="txt", # 文本型 PDF 不做 OCR,扫描件换成 ocr
|
||
page_range="1-20", # 页码从 1 开始,闭区间
|
||
)
|
||
|
||
# markdown() 给人看,to_json() 给程序用,来自同一次解析
|
||
Path("paper.md").write_text(result.markdown(), encoding="utf-8")
|
||
Path("paper.json").write_text(result.to_json(), encoding="utf-8")
|
||
```
|
||
|
||
批量任务使用异步入口,注意一个坏文件不会把整批都拖垮
|
||
|
||
```
|
||
import asyncio
|
||
from pathlib import Path
|
||
from mineru.parser import parse_async
|
||
|
||
asyncdefmain():
|
||
for pdf insorted(Path("./docs").glob("*.pdf")):
|
||
try:
|
||
# 已经处在事件循环里就直接 await,不要外面再套一层
|
||
result = await parse_async(str(pdf), tier="standard")
|
||
Path(f"./out/{pdf.stem}.md").write_text(result.markdown(), encoding="utf-8")
|
||
except Exception as exc:
|
||
print(f"{pdf.name} 解析失败: {exc}")
|
||
|
||
asyncio.run(main())
|
||
```
|
||
|
||
## 有三种部署方式可以选用,根据团队大小来选择
|
||
|
||
一个人使用的话,就直接命令行模式,不要设置为服务,模型下载一次之后就结束
|
||
|
||
两个或者几个业务需要共享同一个模型,并且起 V1 API,模型只加载一次,比每个进程各自使用一份显存要划算得多
|
||
|
||
```
|
||
# V1 API,接口都在 /v1/*,旧的 /file_parse 和 /tasks 在 4.0 已经删了
|
||
mineru-kit api-server --host 0.0.0.0 --port 8000 --tier standard
|
||
|
||
# 多卡或多机,router 统一入口,按 --local-gpus 自动拉 worker
|
||
mineru-kit router --host 0.0.0.0 --port 8002 --local-gpus auto
|
||
```
|
||
|
||
客户端可以复用同一个解析器实例,能力发现、上传、轮询、下载都包含在内,每次调用都会自己打开和关闭会话,并且不需要手动释放
|
||
|
||
```
|
||
from mineru.parser import MinerUApiParser
|
||
|
||
# api_url 填 /v1 之前的根地址,密钥走 MINERU_API_KEY,别写死在代码里
|
||
parser = MinerUApiParser(api_url="http://127.0.0.1:8000", tier="standard")
|
||
print(parser.parse("contract.pdf").markdown())
|
||
```
|
||
|
||
第三种是使用 Gradio 做前端界面, `mineru-kit webui` 起一个,给不会用代码的同事来做人工校验。不要把生产当作接口来使用,它只是一个可视化的外壳
|
||
|
||
## 真正能够留住人的就是那些中间产物
|
||
|
||
很多解析服务只会给你一份 Markdown,看上去很美,但是下游无法使用。除了 Markdown 之外,MinerU 还保留了 middle.json 和 structured\_content.json 两个文件,其中每个块都有 type、page\_idx、bbox 等字段
|
||
|
||
这就意味着你能够自己编写切片逻辑:表格块整体进入向量库,公式块单独抽取出来进行检索,页眉和页脚按照坐标进行过滤。RAG 中最让人头疼的“表格被分割了”的问题,在这层就可以解决了
|
||
|
||
```
|
||
# structured_content 按页给块、按块切比按字符切靠谱得多
|
||
for page in result.structured_content()["pages"]:
|
||
for block in page["blocks"]:
|
||
if block["type"] == "table":
|
||
store_table(block["content"]) # 表格 HTML,行和列的关系仍然存在
|
||
elif block["type"] == "equation":
|
||
store_formula(block["content"]) # LaTeX
|
||
```
|
||
|
||
## 在什么样的情况下不要使用它
|
||
|
||
纯文本 PDF,只要文字不要结构,使用 pypdf 后几十毫秒就可以完成任务,上 MinerU 是拿高射炮打蚊子
|
||
|
||
对于延迟非常敏感的在线接口也不适合,standard 档一次解析是秒级到十几秒级,老老实实做异步任务队列
|
||
|
||
另外还有一个坑要提一下,在 3.1 版本之后,许可证就变成了基于 Apache 2.0 的 MinerU 开源许可证,相比之前的 AGPL 时代更加舒适一些。但是使用之前还是要看一下 LICENSE.md 文件,不要相信别人的一句“随便用”。
|
||
|
||
## 我的判断
|
||
|
||
MinerU 热门并不是因为它的榜单第一,而是在于它可以做到以下三点:可以进行私有化部署、可以批量运行、可以产出结构化的中间结果。做 RAG 的团队里最缺乏的东西并不是再去调用一个云上的 API,而是在于对数据入口的控制
|
||
|
||
我使用的办法是先用 flash 全量跑一遍来做索引,命中率高的文档再走 standard 重解析,可以降低成本一半以上。这套组合拳要比无脑全量 standard 务实性强一些
|
||
|
||
至于它是“最好的”解析器吗?我不会得出这样的结论。但是在我所接触过的项目中,它是我目前少数能够掌握住整个数据链条的工具
|
||
|
||
我是鹏磊,持续分享 AI 编程干货,今天就到这里,我们下期见
|
||
|
||
质保 30 天不掉订阅,掉订阅,按天退差价 |