OpenDataLab/MinerU API设计:RESTful接口完整指南
引言
还在为PDF文档的结构化提取而烦恼吗?面对复杂的文档格式、多语言内容和表格公式混合的场景,传统OCR工具往往力不从心。MinerU作为一站式开源高质量数据提取工具,提供了强大的RESTful API接口,让您能够轻松将PDF转换成结构化的Markdown和JSON格式。
通过本文,您将全面掌握:
- ✅ MinerU RESTful API的核心设计理念
- ✅ 完整的API接口使用方法和参数详解
- ✅ 多格式输出配置和高级功能调用
- ✅ 实战案例和最佳实践指南
- ✅ 错误处理和性能优化技巧
MinerU API架构概述
MinerU采用现代化的FastAPI框架构建RESTful接口,提供高性能、类型安全的API服务。整个API架构遵循RESTful设计原则,支持异步处理和大规模文档批处理。
核心API接口详解
文件解析接口 /file_parse
这是MinerU最核心的API接口,支持多种文件格式的批量处理。
HTTP方法: POST
端点: /file_parse
Content-Type: multipart/form-data
请求参数
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
files | List[UploadFile] | ✅ | - | 上传的文件列表,支持PDF和图像格式 |
output_dir | str | ❌ | ./output | 输出目录路径 |
lang_list | List[str] | ❌ | ["ch"] | 语言列表,支持多语言识别 |
backend | str | ❌ | "pipeline" | 解析后端引擎选择 |
parse_method | str | ❌ | "auto" | 解析方法策略 |
formula_enable | bool | ❌ | true | 是否启用公式解析 |
table_enable | bool | ❌ | true | 是否启用表格解析 |
server_url | str | ❌ | null | SGLang服务器地址 |
return_md | bool | ❌ | true | 返回Markdown格式内容 |
return_middle_json | bool | ❌ | false | 返回中间JSON格式 |
return_model_output | bool | ❌ | false | 返回模型原始输出 |
return_content_list | bool | ❌ | false | 返回内容列表格式 |
return_images | bool | ❌ | false | 返回处理后的图像 |
start_page_id | int | ❌ | 0 | 起始页码(0-based) |
end_page_id | int | ❌ | 99999 | 结束页码(0-based) |
支持的语言类型
MinerU支持丰富的语言识别能力:
SUPPORTED_LANGUAGES = [
"ch", # 中文
"ch_server", # 中文服务器版
"ch_lite", # 中文轻量版
"en", # 英文
"korean", # 韩语
"japan", # 日语
"chinese_cht", # 中文繁体
"ta", # 泰米尔语
"te", # 泰卢固语
"ka", # 卡纳达语
"latin", # 拉丁语系
"arabic", # 阿拉伯语
"east_slavic", # 东斯拉夫语
"cyrillic", # 西里尔字母
"devanagari" # 天城文
]
后端引擎选择
BACKEND_OPTIONS = {
"pipeline": "通用管道处理(推荐)",
"vlm-transformers": "视觉语言模型转换器",
"vlm-sglang-engine": "SGLang引擎加速版",
"vlm-sglang-client": "SGLang客户端模式"
}
实战代码示例
基础使用:单文件解析
import requests
def parse_single_pdf(file_path):
"""解析单个PDF文件"""
url = "http://localhost:8000/file_parse"
with open(file_path, 'rb') as f:
files = {'files': ('document.pdf', f, 'application/pdf')}
data = {
'output_dir': './results',
'lang_list': ['ch'],
'backend': 'pipeline',
'return_md': 'true',
'return_middle_json': 'true'
}
response = requests.post(url, files=files, data=data)
return response.json()
# 使用示例
result = parse_single_pdf("学术论文.pdf")
print(result['results']['学术论文']['md_content'])
高级使用:批量多语言处理
import requests
from pathlib import Path
def batch_process_documents(directory_path, output_base="./output"):
"""批量处理多语言文档"""
url = "http://localhost:8000/file_parse"
pdf_files = list(Path(directory_path).glob("*.pdf"))
image_files = list(Path(directory_path).glob("*.jpg")) + list(Path(directory_path).glob("*.png"))
all_files = pdf_files + image_files
files = []
lang_list = []
for file_path in all_files:
# 根据文件名猜测语言
if "chinese" in file_path.name.lower():
lang_list.append("ch")
elif "english" in file_path.name.lower():
lang_list.append("en")
else:
lang_list.append("ch") # 默认中文
files.append(('files', (file_path.name, open(file_path, 'rb'), 'application/octet-stream')))
data = {
'output_dir': output_base,
'lang_list': lang_list,
'backend': 'pipeline',
'parse_method': 'auto',
'formula_enable': 'true',
'table_enable': 'true',
'return_md': 'true',
'return_middle_json': 'true',
'return_images': 'false'
}
response = requests.post(url, files=files, data=data)
# 关闭所有文件句柄
for _, (_, file_obj, _) in files:
file_obj.close()
return response.json()
生产环境配置示例
import requests
import json
from typing import List, Dict, Any
class MinerUClient:
"""MinerU API客户端类"""
def __init__(self, base_url: str = "http://localhost:8000", timeout: int = 300):
self.base_url = base_url.rstrip('/')
self.timeout = timeout
self.session = requests.Session()
def parse_documents(
self,
file_paths: List[str],
output_dir: str = "./output",
languages: List[str] = None,
backend: str = "pipeline",
enable_formula: bool = True,
enable_table: bool = True,
return_formats: Dict[str, bool] = None
) -> Dict[str, Any]:
"""
解析多个文档
Args:
file_paths: 文件路径列表
output_dir: 输出目录
languages: 语言列表,与文件一一对应
backend: 后端引擎
enable_formula: 是否启用公式解析
enable_table: 是否启用表格解析
return_formats: 返回格式配置
Returns:
解析结果字典
"""
if languages is None:
languages = ["ch"] * len(file_paths)
if return_formats is None:
return_formats = {
"md": True,
"middle_json": True,
"model_output": False,
"content_list": False,
"images": False
}
files = []
for file_path in file_paths:
file_name = Path(file_path).name
files.append(('files', (file_name, open(file_path, 'rb'), 'application/octet-stream')))
data = {
'output_dir': output_dir,
'lang_list': languages,
'backend': backend,
'parse_method': 'auto',
'formula_enable': str(enable_formula).lower(),
'table_enable': str(enable_table).lower(),
'return_md': str(return_formats.get('md', True)).lower(),
'return_middle_json': str(return_formats.get('middle_json', False)).lower(),
'return_model_output': str(return_formats.get('model_output', False)).lower(),
'return_content_list': str(return_formats.get('content_list', False)).lower(),
'return_images': str(return_formats.get('images', False)).lower()
}
try:
response = self.session.post(
f"{self.base_url}/file_parse",
files=files,
data=data,
timeout=self.timeout
)
response.raise_for_status()
return response.json()
finally:
# 确保关闭所有文件句柄
for _, (_, file_obj, _) in files:
file_obj.close()
def get_server_info(self) -> Dict[str, Any]:
"""获取服务器信息"""
response = self.session.get(f"{self.base_url}/info", timeout=10)
response.raise_for_status()
return response.json()
响应格式详解
成功响应示例
{
"backend": "pipeline",
"version": "1.0.0",
"results": {
"document1": {
"md_content": "# 文档标题\n\n这是Markdown格式的文档内容...",
"middle_json": {
"pages": [
{
"page_num": 0,
"width": 595,
"height": 842,
"blocks": [
{
"type": "text",
"bbox": [100, 100, 200, 120],
"text": "这是文本内容",
"confidence": 0.95
}
]
}
]
}
}
}
}
错误响应格式
{
"error": "错误描述信息",
"detail": "详细的错误堆栈信息(开发模式)"
}
高级功能配置
1. 自定义输出格式组合
# 只获取Markdown内容
config1 = {"md": True, "middle_json": False}
# 获取所有可用格式
config2 = {
"md": True,
"middle_json": True,
"model_output": True,
"content_list": True,
"images": True
}
# 仅获取结构化数据
config3 = {"middle_json": True, "content_list": True}
2. 分页处理大型文档
def process_large_document_in_chunks(file_path, chunk_size=50):
"""分块处理大型文档"""
total_pages = get_total_pages(file_path) # 需要实现获取总页数
results = {}
for start_page in range(0, total_pages, chunk_size):
end_page = min(start_page + chunk_size - 1, total_pages - 1)
result = mineru_client.parse_documents(
[file_path],
start_page_id=start_page,
end_page_id=end_page,
return_formats={"md": True}
)
results[f"pages_{start_page}_{end_page}"] = result
return results
3. 多后端性能对比
def benchmark_backends(file_path):
"""对比不同后端的性能"""
backends = ["pipeline", "vlm-transformers", "vlm-sglang-engine"]
results = {}
for backend in backends:
start_time = time.time()
result = mineru_client.parse_documents(
[file_path],
backend=backend,
return_formats={"md": True}
)
end_time = time.time()
results[backend] = {
"processing_time": end_time - start_time,
"result": result
}
return results
部署和运维指南
Docker部署示例
version: '3.8'
services:
mineru-api:
image: opendatalab/mineru:latest
ports:
- "8000:8000"
volumes:
- ./data:/app/data
- ./output:/app/output
environment:
- MINERU_DEVICE_MODE=cuda
- MINERU_VIRTUAL_VRAM_SIZE=8
- MINERU_MODEL_SOURCE=huggingface
command: mineru-api --host 0.0.0.0 --port 8000
性能优化配置
# 环境变量配置
export MINERU_DEVICE_MODE=cuda:0
export MINERU_VIRTUAL_VRAM_SIZE=12
export MINERU_MODEL_SOURCE=modelscope
export MINERU_FORMULA_ENABLE=true
export MINERU_TABLE_ENABLE=true
# 启动高性能模式
mineru-api --host 0.0.0.0 --port 8000
错误处理和重试机制
import requests
import time
from tenacity import retry, stop_after_attempt, wait_exponential
class RobustMinerUClient:
"""带重试机制的MinerU客户端"""
def __init__(self, base_url: str, max_retries: int = 3):
self.base_url = base_url
self.max_retries = max_retries
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10)
)
def parse_with_retry(self, file_path: str, **kwargs):
"""带重试的文档解析"""
try:
return self._parse_document(file_path, **kwargs)
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}, 进行重试...")
raise
def _parse_document(self, file_path: str, **kwargs):
"""实际的文档解析逻辑"""
# 实现解析逻辑
pass
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



