MinerU - 将非结构化文档(PDF、图片、Office 文件等)转换为机器可读的 Markdown 和 JSON


MinerU 是一款开源高精度文档解析引擎,将非结构化文档(PDF、图片、Office 文件等)转换为机器可读的 Markdown 和 JSON,专为 LLM 预训练、RAG 和 Agent 工作流场景设计。
当前整体效果仍在持续改进中。如果你遇到效果不理想、输出质量不稳定或明显的版式异常,欢迎提交 issue 或附带样例文件 / 截图反馈。

核心解析能力:

  • 公式 → LaTeX · 表格 → HTML,精准还原复杂版面
  • 支持扫描件、手写体、多栏布局、跨页表格合并
  • 输出符合人类阅读顺序,自动去除页眉页脚
  • VLM + OCR 双引擎,支持 109 种语言识别

🐍 Python SDK

安装

pip install mineru-open-sdk
uv add mineru-open-sdk --default-index https://pypi.tuna.tsinghua.edu.cn/simple

Agent 轻量解析(免 Token)

from mineru import MinerU

client = MinerU()
result = client.flash_extract("https://cdn-mineru.openxlab.org.cn/demo/example.pdf")
print(result.markdown)

精准解析(需 Token)

from mineru import MinerU

# 从 https://mineru.net 获取免费 Token
client = MinerU("your-api-token")
result = client.extract("https://cdn-mineru.openxlab.org.cn/demo/example.pdf")
print(result.markdown)
print(result.images)  # 提取的图片列表

🦜 LangChain RAG 集成

langchain-mineru 是官方 LangChain 文档加载器,一行代码将任意文档转为 LangChain Document 对象,直接接入 RAG 流水线。

安装

pip install langchain-mineru

最简示例(无需 Token)

1. 基础用法(默认 flash 模式,无需 Token)

from langchain_mineru import MinerULoader

loader = MinerULoader(source="demo.pdf")   # 默认 flash 模式,无需 Token
docs = loader.load()
print(docs[0].page_content[:500])
print(docs[0].metadata)

默认使用 mode="flash",适合快速预览和轻量解析。

2. Precision 模式(需 Token)

适合长文档、大文件,以及对解析保真度或标准 API 输出要求更高的场景。Flash 模式也支持 OCR、公式、表格开关,但仍受 flash API 自身限制。

from langchain_mineru import MinerULoader

loader = MinerULoader(
    source="/path/to/manual.pdf",
    mode="precision",
    token="your-api-token",  # 或设置 MINERU_TOKEN 环境变量
    split_pages=True,
    pages="1-5",
)

docs = loader.load()
for doc in docs:
    print(doc.metadata.get("page"), doc.page_content[:200])

3. 接入 LangChain RAG 流水线

from langchain_mineru import MinerULoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS

loader = MinerULoader(source="demo.pdf", split_pages=True)
docs = loader.load()

splitter = RecursiveCharacterTextSplitter(chunk_size=1200, chunk_overlap=200)
chunks = splitter.split_documents(docs)

vs = FAISS.from_documents(chunks, OpenAIEmbeddings())
results = vs.similarity_search("这个文档的核心结论是什么?", k=3)
for r in results:
    print(r.page_content[:200])

默认使用 mode="flash"(无需 API Token);切换到 mode="precision" 可获得更高精度的解析结果(需要 Token 认证)。如果用于 RAG,建议对 PDF 开启 split_pages=True,这样可以得到更细粒度的页级 Document

🔗 全部集成

框架 / 工具 状态 说明
LangChain ✅ 官方 pip install langchain-mineru
LlamaIndex ✅ 社区 见 MinerU-Ecosystem
RAGFlow ✅ 支持 文档加载器集成
RAG-Anything ✅ 支持 多模态 RAG 流水线
Flowise ✅ 支持 可视化 RAG 构建器
Dify ✅ 原生插件 内置文档加载器
FastGPT ✅ 原生插件 接入文档
Claude Desktop ✅ MCP uvx mineru-open-mcp
Cursor ✅ MCP .cursor/mcp.json 配置
Windsurf ✅ MCP stdio / streamable-http
OpenClaw / ZeroClaw ✅ Agent 技能 ClawHub
Go SDK ✅ 官方 go get .../sdk/go@latest
TypeScript SDK ✅ 官方 npm install mineru-open-sdk
Python SDK ✅ 官方 pip install mineru-open-sdk

MinerU Open API SDK (Python)

MinerU Open API SDK 是一个完全免费的 Python 库,用于连接 MinerU 文档提取服务。只需一行代码,即可将任何文档(PDF、图片、Word、PPT、Excel)或网页转换为高质量的 Markdown。


🚀 核心特性

  • 完全免费:文档提取服务没有任何隐藏费用。
  • Agent 轻量解析 (No Auth):无需 API Token 即可立即提取。
  • 精准解析:提供完整的版式保留、图片、表格及公式支持。
  • 批量与轮询原语:既提供开箱即用的阻塞式接口,也提供适合异步工作流的 submit/query 接口。
  • 内置保存辅助方法:可直接保存 Markdown、HTML、LaTeX、DOCX,或解压完整结果包。

📦 安装指南

pip install mineru-open-sdk

🛠️ 快速上手

1. Agent 轻量解析 (Flash Extract - 免登录)

适合快速预览。无需配置 Token。

from mineru import MinerU

# Agent 轻量解析无需传入 Token
client = MinerU()
result = client.flash_extract("https://cdn-mineru.openxlab.org.cn/demo/example.pdf")

print(result.markdown)

2. 精准解析 (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)
print(result.images) # 获取提取出的图片列表

🧩 支持的公开接口

Client 生命周期

  • MinerU(token: str | None = None, base_url: str = ..., flash_base_url: str | None = None)
  • client.close()
  • client.set_source("your-app")
  • 支持上下文管理器:with MinerU(...) as client:

阻塞式解析接口

  • client.extract(...) -> ExtractResult
  • client.extract_batch(...) -> Iterator[ExtractResult]
  • client.crawl(...) -> ExtractResult
  • client.crawl_batch(...) -> Iterator[ExtractResult]
  • client.flash_extract(...) -> ExtractResult

提交 / 查询接口

  • client.submit(...) -> str
  • client.submit_batch(...) -> str
  • client.get_batch(batch_id) -> list[ExtractResult]
  • client.get_task(task_id) -> ExtractResult

结果保存辅助方法

  • result.save_markdown(path, with_images=True)
  • result.save_docx(path)
  • result.save_html(path)
  • result.save_latex(path)
  • result.save_all(dir)
  • image.save(path)

常用结果字段

  • result.state
  • result.progress
  • result.markdown
  • result.images
  • result.content_list
  • result.docx
  • result.html
  • result.latex
  • result.task_id

📊 模式对比

特性 Agent 轻量解析 (Flash) 精准解析 (Precision)
身份认证 免登录 (No Auth) 需登录 (Token)
处理速度 极速 标准
文件大小上限 最大 10 MB 最大 200 MB
文件页数上限 最大 20 页 最大 200 页
支持格式 PDF, 图片, Docx, PPTx, Excel PDF, 图片, Doc/x, Ppt/x, Html
内容完整度 Markdown(公式和表格默认开启,OCR 默认关闭) 完整资源 (图片、表格、公式全部保留)
输出格式 Markdown MD, Docx, LaTeX, HTML, JSON

⚙️ 默认行为与参数说明

MinerU(...)

参数 默认值 省略时行为
token None 若未传入,则读取环境变量 MINERU_TOKEN
base_url https://mineru.net/api/v4 标准 API 的默认地址
flash_base_url SDK 内置默认 flash 地址 可用于测试或私有部署

如果既没有传入 token,环境变量 MINERU_TOKEN 也未设置,则 client 进入 flash-only modeflash_extract() 可用,其他需要鉴权的方法会抛出 NoAuthClientError

全功能接口

这些默认值适用于 extract()extract_batch()submit()submit_batch()crawl() / crawl_batch() 也会间接继承其中的大部分行为。

参数 默认值 省略时行为
model None 自动推断:.html / .htm"html",其余默认 "vlm"
ocr 不设置 默认关闭 OCR(API 默认行为)
formula 不设置 默认开启公式识别(API 默认行为)
table 不设置 默认开启表格识别(API 默认行为)
language 不设置 默认中文 "ch"(API 默认行为)
pages None 默认处理完整文档
extra_formats None 仅返回默认的 Markdown / JSON 结果
file_params None 批量方法中的 per-file 参数覆盖。dict[str, FileParam],key 为路径/URL,FileParam 包含 pagesocrdata_id 字段
timeout 单任务 300 extract() / crawl() 的总轮询超时
timeout 批量 1800 extract_batch() / crawl_batch() 的总轮询超时

Flash Extract

参数 默认值 省略时行为
language "ch" 默认中文
page_range None 默认处理 flash API 允许的完整页范围
is_ocr None OCR 默认关闭(API 默认行为)
enable_formula None 公式识别默认开启(API 默认行为)
enable_table None 表格识别默认开启(API 默认行为)
timeout 300 总轮询超时

crawl() / crawl_batch()

  • crawl() 等价于 extract(url, model="html", ...)
  • crawl_batch() 等价于 extract_batch(urls, model="html", ...)

📖 详细用法

全功能提取选项

result = client.extract(
    "./论文.pdf",
    model="vlm",             # "vlm" | "pipeline" | "html"
    ocr=True,                # 启用 OCR 识别扫描件
    formula=True,            # 公式识别
    table=True,              # 表格识别
    language="en",           # "ch" | "en" | 等
    pages="1-20",            # 页码范围
    extra_formats=["docx"],  # 额外导出为 docx, html, 或 latex
    timeout=600,
)

result.save_all("./output/") # 保存 Markdown 和所有相关资源

上下文管理器

from mineru import MinerU

with MinerU("your-api-token") as client:
    result = client.extract("./论文.pdf")
    print(result.markdown)

批量处理

# 边处理边返回结果
for result in client.extract_batch(["a.pdf", "b.pdf", "c.pdf"]):
    print(f"{result.filename}: 已完成")

批量处理 - 为每个文件指定不同页码

from mineru import FileParam

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

网页爬取 (Crawl)

result = client.crawl("https://www.baidu.com")
print(result.markdown)

🔄 submit() / get_batch() 语义说明

这一组接口最容易被误用:

  • submit() 返回的是 batch_id
  • submit_batch() 返回的也是 batch_id
  • 因此最常见的异步流程应该是 submit(...) -> get_batch(batch_id)
  • 对于异步轮询,建议始终沿用 batch 这一套语义

推荐的异步流程

batch_id = client.submit("大报告.pdf")

# 轮询 batch,直到第一个结果完成
while True:
    results = client.get_batch(batch_id)
    result = results[0]
    if result.state in ("done", "failed"):
        break

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

🤖 AI Agent 自动化集成

本 SDK 设计时充分考虑了 LLM 工作流集成。您可以通过 result.stateresult.progress 轻松监控任务状态。

batch_id = client.submit("大报告.pdf")
# ... 稍后 ...
result = client.get_batch(batch_id)[0]
if result.state == "done":
    do_something(result.markdown)

发票快速生成汇总表

PDF 发票 → MinerU SDK 批量提取 → LLM 结构化提取 → Excel

pip install mineru-open-sdk openai openpyxl python-dotenv

.env

MINERU_TOKEN=你的MinerU Token
LLM_API_KEY=你的Moonshot API Key
LLM_BASE_URL=https://api.moonshot.cn/v1
LLM_MODEL=moonshot-v1-128k

完整代码

整个脚本只有三个函数。关键设计:extract_batch 是 yield 式返回——解完一张就立刻喂给 LLM,不用等全部解完。

"""
MinerU 发票提取器
PDF 发票 → MinerU SDK 批量提取 JSON → LLM 结构化提取 → Excel
"""
import os
import sys
import json
from pathlib import Path
from dotenv import load_dotenv

from mineru import MinerU, FileParam
from openai import OpenAI
from openpyxl import Workbook

# -------- 加载环境变量 --------
load_dotenv()

MINERU_TOKEN = os.getenv("MINERU_TOKEN")
LLM_API_KEY = os.getenv("LLM_API_KEY")
LLM_BASE_URL = os.getenv("LLM_BASE_URL", "https://api.moonshot.cn/v1")
LLM_MODEL = os.getenv("LLM_MODEL", "moonshot-v1-128k")

EXTRACT_PROMPT = (
    '你是一个发票信息提取器。以下是MinerU SDK从发票图片中提取的content_list。'
    '每个文本块格式:{"type": "text", "text": "发票号码:144000000000", ...} '
    '或 {"type": "table", "table_body": "<table>...<td>价税合计(小写)</td>'
    '<td>¥ 90000.00</td>...</table>"}。'
    '请找出:1)发票号码(以"发票号码:"开头的text冒号后数字) '
    '2)开票日期("开票日期:"开头,转YYYY-MM-DD) '
    '3)价税合计(表格中"价税合计(小写)"对应¥后面数字)。'
    '只返回JSON,不要任何解释或思考过程。'
    '格式:{"invoice_number":"","date":"","total":""}'
)


# -------- 函数 1:MinerU 批量解析,解完一个 yield 一个 --------
def parse_invoices(pdf_dir: str):
    """将目录下所有 PDF/图片通过 MinerU SDK 批量提取,解完一个 yield 一个"""
    files = []
    for ext in ["*.pdf", "*.jpg", "*.jpeg", "*.png", "*.bmp"]:
        files.extend(sorted(Path(pdf_dir).glob(ext)))
    if not files:
        print("No files found (supported: pdf, jpg, png, bmp)")
        return

    client = MinerU(MINERU_TOKEN)

    # extract_batch 支持的全局参数:
    #   model     - 模型版本: "vlm"(推荐) / "pipeline" / "html",默认自动推断
    #   ocr       - 是否开启 OCR,默认 False
    #   formula   - 是否开启公式识别,默认 True
    #   table     - 是否开启表格识别,默认 True
    #   language  - 文档语言,默认 "ch"
    #   extra_formats - 额外导出格式: ["docx", "html", "latex"]
    #   timeout   - 轮询超时秒数,默认 1800
    #   file_params - 按文件覆盖参数,key 为文件路径,value 为 FileParam

    # FileParam 支持的字段:
    #   pages   - 页码范围,如 "1-5"
    #   ocr     - 覆盖全局 OCR 开关
    #   data_id - 自定义业务标识

    # 发票是扫描件/图片,需要开 OCR;通过 FileParam 按文件设置参数
    file_params = {str(f): FileParam(ocr=True) for f in files}
    for result in client.extract_batch(
        [str(f) for f in files],
        table=True,         # 发票中的金额在表格里,确保开启
        file_params=file_params,
    ):
        print(f"  Parsed: {result.filename}")
        yield {"filename": result.filename, "content": result.content_list}
    client.close()


# -------- 函数 2:LLM 提取结构化字段 --------
def extract_fields(invoice: dict, llm: OpenAI) -> dict:
    """将单张发票的 content_list 喂给 LLM,提取发票号码/日期/金额"""
    content_str = json.dumps(invoice["content"], ensure_ascii=False)
    resp = llm.chat.completions.create(
        model=LLM_MODEL,
        messages=[{"role": "user", "content": EXTRACT_PROMPT + content_str}],
        temperature=0,
    )
    raw = resp.choices[0].message.content.strip()
    try:
        fields = json.loads(raw)
    except json.JSONDecodeError:
        fields = {"invoice_number": "PARSE_ERROR", "date": "", "total": ""}
    fields["filename"] = invoice["filename"]
    print(f"  Extracted: {invoice['filename']}")
    return fields


# -------- 函数 3:写入 Excel --------
def write_excel(data: list[dict], output: str = "发票汇总.xlsx"):
    """将提取结果写入 Excel"""
    wb = Workbook()
    ws = wb.active
    ws.append(["文件名", "发票号码", "开票日期", "价税合计"])
    for row in data:
        ws.append([
            row.get("filename"),
            row.get("invoice_number"),
            row.get("date"),
            row.get("total")
        ])
    wb.save(output)
    print(f"已保存: {output}")


# -------- 主流程:流水线式处理 --------
def main():
    pdf_dir = sys.argv[1] if len(sys.argv) > 1 else "./invoices"
    llm = OpenAI(api_key=LLM_API_KEY, base_url=LLM_BASE_URL)

    results = []
    for invoice in parse_invoices(pdf_dir):        # 解完一张
        results.append(extract_fields(invoice, llm))   # 立刻提取

    write_excel(results)

if __name__ == "__main__":
    main()
python invoice_extractor.py ./invoices

image

MinerU 在线 API 实战教程
MinerU 多环境部署实践:从开源容器化到信创生态适配

posted @ 2026-06-24 14:25  VipSoft  阅读(21)  评论(0)    收藏  举报