mineru-open-sdk 深度指南(Python 版):从 pip install 到百万页文档批处理

77 阅读12分钟

Python## 1. 安装与环境配置

pip install mineru-open-sdk

一行命令,安装完成。mineru-open-sdk 是 MinerU 官方提供的 Python SDK,通过它你可以直接调用 MinerU 的文档解析服务,不需要手动拼接 REST API、处理签名逻辑或维护轮询状态机。

Python 版本要求 >=3.10。SDK 的运行时依赖极轻——除了 httpx>=0.27,没有额外的重量级包(如 torch、tensorflow)。这意味着你可以在任何 Python 3.10+ 环境中快速集成,包括 Docker 容器、CI/CD Pipeline、无服务器函数(如 AWS Lambda 或阿里云函数计算)。

安装后验证:

from mineru import MinerU
print(MinerU.__name__)  # mineru

SDK 自动识别当前环境是否有 MINERU_TOKEN 环境变量。如果你配置了 Token,MinerU() 会进入完整功能模式;如果没有,则自动降级为 Flash-only 模式——这在第 2 节会详细展开。

2. 快速上手:两种解析模式

mineru-open-sdk 提供两种解析入口,对应完全不同的使用场景:Flash Extract(Agent 轻量解析)和 Precision Extract(精准解析)。选对模式,比写对代码更重要。

Flash Extract:免 Token,10 秒出结果

Flash Extract 面向快速预览场景:不需要注册、不需要申请 Token、不需要配置任何认证信息。它适合 AI Agent 工作流中临时解析一个链接的场景。

from mineru import MinerU

client = MinerU()  # 不传 Token,自动进入 flash-only mode
result = client.flash_extract("https://cdn-mineru.openxlab.org.cn/demo/example.pdf")

print(result.markdown)

约束条件需要清楚:

维度限制
文件大小≤ 10 MB
页数≤ 20 页
支持格式PDF、图片、Docx、PPTx、Excel
输出格式仅 Markdown
认证无(IP 限频)

Flash Extract 返回的 result.markdown 包含 Markdown 文本。默认开启公式识别和表格识别,OCR 默认关闭。对扫描件场景,你需要手动开启 is_ocr=True

Precision Extract:完整管线,全格式输出

当你需要完整结构——不仅仅是文本,还有图片资源、表格数据、公式 LaTeX,甚至同时导出 DOCX 和 HTML——就用 Precision Extract。

from mineru import MinerU

# 从 https://mineru.net/apiManage/token 获取免费 Token
client = MinerU("your-api-token")
result = client.extract("https://cdn-mineru.openxlab.org.cn/demo/example.pdf")

print(result.markdown)       # Markdown 全文
print(result.images)         # 提取出的图片列表
print(result.html)           # HTML 格式
print(result.docx)           # DOCX 二进制内容
print(result.latex)          # LaTeX 格式

result 是一个 ExtractResult 对象,包含多个输出字段。你可以在一次调用中同时获取所有格式,不需要多次请求。其中 result.markdown 是最常用的字段,包含了完整的文档内容、版面结构和公式/表格的 Markdown 表示。

两种模式的输出字段对比

字段Flash ExtractPrecision Extract
result.markdown
result.images
result.html
result.docx
result.latex
result.content_list

选择策略很简单:文件小于 10 MB、不超过 20 页、只需 Markdown 输出 → Flash Extract。其他场景一律 Precision Extract,特别是需要图片资源、DOCX/LaTeX 导出、或文件超过 20 页时。

3. 三种生产级调用模式

从本地原型到生产系统,调用模式需要逐步升级。mineru-open-sdk 覆盖了三层递进场景。

模式一:本地文件直接解析

开发阶段最常用的方式。支持本地文件路径、URL 两种输入形式。

from mineru import MinerU

with MinerU("your-api-token") as client:
    # 本地文件
    result = client.extract("./report.pdf")
    print(result.markdown)

    # 远程 URL
    result2 = client.extract("https://example.com/invoice.pdf")
    print(result2.markdown)

使用上下文管理器(with 语句)时,SDK 会在退出时自动关闭 HTTP 连接池。你也可以手动管理生命周期:

client = MinerU("your-api-token")
result = client.extract("./report.pdf")
client.close()

extract() 支持多个参数控制解析行为:

result = client.extract(
    "./论文.pdf",
    model="vlm",              # "vlm" | "pipeline" | "html"
    ocr=True,                 # 启用 OCR
    formula=True,             # 公式识别(默认开启)
    table=True,               # 表格识别(默认开启)
    language="ch",            # 文档语言
    pages="1-20",             # 页码范围
    extra_formats=["docx"],   # 额外导出格式
    timeout=600,              # 轮询超时(秒)
)

model 参数值得单独说清楚:vlm 使用视觉语言模型解析,精度最高,适合复杂版面;pipeline 使用传统管线,速度更快;html 专门用于网页内容抓取,等价于调用 crawl() 方法。对学术论文、扫描件、图文混排文档,推荐使用 model="vlm"

模式二:Open API 远程调用

当你的应用需要跨网络调用 MinerU 服务,或者你正在构建一个多租户系统,Open API 模式更合适。SDK 封装了完整的鉴权和轮询逻辑,你不需要手动处理 Authorization 头或任务状态机。

from mineru import MinerU

client = MinerU("your-api-token", base_url="https://mineru.net/api/v4")
result = client.extract("https://cdn-mineru.openxlab.org.cn/demo/example.pdf")

base_url 默认指向 MinerU 公共 API。如果你使用私有化部署或区域化服务节点,替换这个地址即可。SDK 内部使用 httpx 客户端管理连接,支持连接池复用(见第 6 节性能调优)。

Precision Extract 的文件限制:

限制项
文件大小≤ 200 MB
页数≤ 200 页
每日免费额度1000 页最高优先解析
单次批量≤ 50 个文件(URL 模式)
网络限制GitHub、AWS 等国外 URL 可能超时

模式三:私有化部署接入

如果你的数据不能上云,MinerU 提供开源版私有化部署。SDK 通过 base_url 参数无缝对接私有实例。

from mineru import MinerU

# 假设私有部署地址为 https://mineru.internal.company.com
client = MinerU("internal-token", base_url="https://mineru.internal.company.com/api/v4")
result = client.extract("./机密报告.pdf")

私有化部署模式下,所有解析在本地完成,数据不出内网。SDK 接口与云 API 完全一致,代码切换成本为零——换个 base_urltoken 就行。

4. 批量处理与异步工作流

单文件解析只是起点。生产环境中,你需要处理的是成百上千个文档——合同审核、论文批量解析、票据数据提取、历史档案数字化。mineru-open-sdk 为此提供了两套互补的原语。

阻塞式批处理:extract_batch()

如果你希望"提交一批文件,依次拿到结果"——像是遍历一个文件列表,每个文件解析完成后立刻处理——用 extract_batch()

from mineru import MinerU

files = [
    "contract_001.pdf",
    "contract_002.pdf",
    "report_2024.pdf",
    "invoice_march.pdf",
    "https://example.com/spec.pdf",
]

with MinerU("your-api-token") as client:
    for result in client.extract_batch(files):
        print(f"{result.filename}: state={result.state}")
        if result.state == "done":
            # 每完成一个文件,立即处理
            with open(f"./output/{result.filename}.md", "w") as f:
                f.write(result.markdown)

extract_batch() 返回一个迭代器,按文件的提交顺序逐个 yield ExtractResult。一个文件完成后,你可以立刻处理它的结果,不需要等待整批完成。这种行为对内存很友好——你不需要在内存里同时持有几百个文件的结果。

默认超时时间为 1800 秒(30 分钟)。你可以通过 timeout 参数调整:

results = client.extract_batch(files, timeout=3600)

异步 submit/query 原语

如果你的工作流更复杂——需要把文件提交到队列后去做其他事情,之后再回来查结果——使用 submit() + get_batch() 组合。

from mineru import MinerU

client = MinerU("your-api-token")

# 提交单个文件,返回 batch_id(注意:submit 返回的也是 batch_id)
batch_id = client.submit("大报告.pdf")

# ... 做其他事情 ...

# 轮询 batch,直到结果完成
while True:
    results = client.get_batch(batch_id)
    result = results[0]
    if result.state in ("done", "failed"):
        break
    print(f"进度: {result.state}")

if result.state == "done":
    print(result.markdown)

这一组接口最容易被误用。SDK 的设计中,submit()submit_batch() 都返回 batch_id。这意味着你始终通过 batch 语义来查询——即使你只提交了一个文件。对应的查询方法是 get_batch(batch_id),返回一个结果列表。

批量提交 + 文件级别参数覆盖

当批次中的每个文件需要不同的解析参数时,使用 file_params

from mineru import MinerU, FileParam

batch_id = client.submit_batch(
    ["a.pdf", "b.pdf"],
    file_params={
        "a.pdf": FileParam(pages="1-5", ocr=True),
        "b.pdf": FileParam(pages="10-20"),
    },
)

错误隔离与重试策略

批量处理时,单个文件的失败不会影响批次中的其他文件。你可以在迭代结果时逐个检查 result.state 和可选的 result.err_msg

for result in client.extract_batch(files):
    if result.state == "failed":
        # 记录失败,不阻塞整个批次
        failed_files.append(result.filename)
        continue
    process_result(result)

一个实用的重试策略:对失败的文件收集后单独重试,最多重试 3 次,每次间隔指数退避(1s → 2s → 4s)。

内存与并发控制

extract_batch() 内部会限制并发请求数以防止客户端内存溢出。如果你需要更高的吞吐,可以调整 httpx 客户端的连接池配置:

import httpx
from mineru import MinerU

transport = httpx.AsyncHTTPTransport(connections=10)
client = MinerU("token", base_url="...")
# 内部 client 可以通过 client._client 访问 httpx.AsyncClient

根据经验估算,一个中等配置的服务器(4 核 8G)使用默认并发设置处理 1000 份 PDF(平均 10 页/份),总耗时约 15-25 分钟,取决于文件复杂度和网络延迟。

5. 结果保存与格式选型

解析完成后,如何保存结果直接影响下游工作流效率。ExtractResult 提供了 5 个内置保存方法,覆盖 RAG 流水线、文档编辑、网页展示三种典型场景。

save_markdown() — RAG 流水线的标准输入

result.save_markdown("./output/", with_images=True)

保存一个 {filename}.md 文件和一个 {filename}_images/ 目录(如果解析结果中包含图片)。Markdown 是目前 RAG 流水线中最通用的文档格式——它保留了标题层级、列表、表格和公式,同时可以被几乎所有文本切分工具(如 LangChain 的 MarkdownHeaderTextSplitter)直接消费。

save_docx() — 文档编辑与办公协作

result.save_docx("./output/report.docx")

当最终用户需要对解析结果做二次编辑——比如调整排版、补充批注、合并多份文档——DOCX 是更自然的选择。MinerU 会将版面结构映射为 Word 的原生段落、表格和图片样式,保留多栏布局和脚注相对位置。

save_html() — 网页展示与在线预览

result.save_html("./output/report.html")

HTML 格式适合在线文档系统、知识库页面和 Web 应用。生成的 HTML 保持了原始的标题结构和图片内嵌引用,可以直接嵌入 iframe 或通过静态站点发布。

save_latex() — 学术出版与论文排版

result.save_latex("./output/paper.tex")

LaTeX 输出主要面向学术场景。如果源文档是高密度数学论文,LaTeX 格式保留了完整的公式表达和交叉引用结构,可以直接用于 Overleaf 或 TeX 编辑器的二次排版。

save_all() — 一键打包,保留完整资产

result.save_all("./output/full_result/")

save_all() 是最高层级的保存方法,它会解压完整结果包,输出目录结构如下:

output/full_result/
├── full.md                  # Markdown 全文
├── content_list.json        # 结构化内容列表
├── images/                  # 所有提取出的图片
│   ├── img_001.png
│   ├── img_002.jpg
│   └── ...
├── document.docx            # (如果 extra_formats 包含 docx)
├── document.html            # (如果 extra_formats 包含 html)
└── document.tex             # (如果 extra_formats 包含 latex)

下游衔接建议

下游场景推荐格式原因
RAG / 向量检索Markdown标题层级清晰,切分语义准确
文档编辑器(Word/Google Docs)DOCX原生格式,所见即所得
Web 内容展示HTML浏览器原生渲染,支持 CSS 样式
学术论文排版LaTeX公式和引用完整保留
全量归档save_all()一次性保存所有格式和资产

6. 性能调优与常见问题

超时设置

不同文件大小需要不同的超时配置。经验值:

# 小文件(<50 页)
client.extract("小文件.pdf", timeout=120)

# 大文件(50-200 页)
client.extract("大文件.pdf", timeout=600)

# 批量(100+ 文件)
client.extract_batch(files, timeout=3600)

单任务默认超时 300 秒,批量默认 1800 秒。如果文件普遍超过 100 页,建议将超时增加到 600 秒以上。

大文件分片

当文件超过 200 页或 200 MB 时,API 不支持直接解析。解决方案是在提交前拆分文件:

# 手动指定页码范围
result_part1 = client.extract("大报告.pdf", pages="1-100")
result_part2 = client.extract("大报告.pdf", pages="101-200")

对于超过 200 页的 PDF,建议先用 PyMuPDF 或 pdfplumber 拆分为多个子文件,再通过 extract_batch() 批量提交。

连接池复用

每次创建 MinerU() 实例都会初始化一个新的 HTTP 连接池。在高吞吐场景下,复用同一个实例:

# 推荐:复用 client 实例
client = MinerU("token")
for file in thousands_of_files:
    result = client.extract(file)
    process(result)
client.close()

常见问题与解决方法

Q: flash_extract() 返回空内容或报错

检查文件是否超过 10 MB 或 20 页。Flash API 对超限文件直接拒绝(HTTP 429 或错误码 -30003)。如果文件参数合规,检查 URL 是否为可公开访问的 CDN 地址——GitHub raw 链接、需要登录的网盘链接可能无法访问。

Q: extract() 报 Token 错误(错误码 A0202/A0211)

检查 Token 是否过期。Token 可以在 MinerU Token 管理页 续期。另一个常见问题是 Token 字符串中包含空格或换行符——建议从页面直接复制。

Q: 批量处理时部分文件一直 pending

Pending 状态通常是排队拥挤导致。MinerU 每天前 1000 页使用最高优先级队列,超过的部分自动降级。如果你的批量任务中有大量超 1000 页的文档,建议分批提交,避免所有文件挤在低优先级队列。

Q: 国外 URL(GitHub、AWS)请求超时

API 文档明确指出,因网络限制,GitHub、AWS 等国外 URL 会请求超时(错误码 -60008)。解决方案:先将文件下载到本地或上传到国内 CDN,再提交本地路径。

Q: 如何确认解析进度?

result = client.extract("大文件.pdf")
# extract() 会阻塞直到完成
# 但你可以通过 submit() + get_batch() 获取中间进度
print(result.state)       # "done" | "failed"
print(result.progress)    # 如果 state 为 running,包含已解析页数

错误码速查

错误码含义解决方向
A0202Token 错误检查 Token 和 Bearer 前缀
A0211Token 过期到 Token 管理页续期
-60005文件超过 200 MB拆分文件
-60006文件超过 200 页拆分或指定 page_ranges
-60008文件读取超时检查 URL 可达性
-30003Flash 接口页数超限改用 Precision Extract
-60018当日解析额度用尽明日后重试或升级套餐