Skip to content
共绩算力文档中心

容器化部署 minerU

更新(2025 年 9 月 26 日)

目前平台上的镜像已经更新到 minerU 2.5.3,相关功能与原先有所差异。

minerU2.5 后推理后端从 sglang 更改为 vllm。web UI 与 api 支持独自部署。平台默认启动 web UI,可通过环境变量USE_API=true部署 api 服务。

🌹

此镜像提供了标准化的 API 接口和 web UI 界面,让您能够便捷地访问和使用所有功能。

本指南详细阐述了在共绩算力平台上,高效部署与使用 minerU API 项目的技术方案。minerU 是一款将 PDF 转化为机器可读格式的工具(如 markdown、json),可以很方便地输出为任意格式。

共绩算力平台提供预构建的 minerU 容器镜像,用户无需本地复杂环境配置,可快速完成部署并启用服务。以下是详细部署步骤:

登录共绩算力控制台,在控制台首页点击“弹性部署服务”进入管理页面。首次使用需确保账户已开通弹性部署服务权限。

根据实际需求选择 GPU 型号:

初次使用或调试阶段,推荐配置单张 NVIDIA RTX 4090 GPU

在“服务配置”模块切换至“预制服务”选项卡,搜索并选择 minerU 官方镜像。

点击“部署服务”,平台将自动拉取镜像并启动容器。

2.快速上手—— web UI 界面使用说明

Section titled “2.快速上手—— web UI 界面使用说明”

点击 7860 端口对应的链接进入 web UI 界面

上传完成后即可开始解析:

启动前设置环境变量 USE_API=true 部署完成后,在“快捷访问”中复制端口为 8000 的公网访问链接,后续是通过该地址调用 API 服务。

地址后面加上 /docs 进入 API 接口文档

import requests
import json
import os
from pathlib import Path
import base64
API_URL = "https://test-mineru-service-239-4vxz4deq-8000.550c.cloud/file_parse"
FILES = [
r"C:\Users\27461\Downloads\ 13710204986.pdf",
]
OPTIONS = {
"output_dir": None,
"lang_list": ["ch", "en"],
"backend": "vlm-sglang-client",
"parse_method": "auto",
"formula_enable": True,
"table_enable": True,
"server_url": "http://localhost:30000",
"return_md": True,
"return_middle_json": False,
"return_model_output": False,
"return_content_list": False,
"return_images": True,
"start_page_id": 0
}
def get_file_key(file_path):
path = Path(file_path)
return path.stem
def save_md_content(md_content, output_path="output.md"):
with open(output_path, "w", encoding="utf-8") as f:
f.write(md_content)
print(f"📄 Markdown 内容已保存至 {output_path}")
def save_images(images, output_dir="output_images"):
os.makedirs(output_dir, exist_ok=True)
# 🔴 修复:images 是 dict,不是 list
if isinstance(images, dict):
items = images.items()
elif isinstance(images, list):
items = enumerate(images)
else:
print("❌ images 格式不支持,类型:", type(images))
return
saved_count = 0
for key, img_b64 in items:
try:
if not isinstance(img_b64, str):
print(f"❌ 图片 {key} 不是字符串,跳过")
continue
# 去除 data:image/xxx;base64, 前缀
if "," in img_b64:
img_b64 = img_b64.split(",", 1)[1]
# 补齐 padding
missing_padding = len(img_b64) % 4
if missing_padding:
img_b64 += "=" * (4 - missing_padding)
# 解码
img_bytes = base64.b64decode(img_b64)
# 使用 key 作为文件名,或用序号
if isinstance(key, str):
img_name = key # 保留原始文件名,如 "image_0.png"
else:
img_name = f"image_{saved_count:03d}"
img_path = Path(output_dir) / f"{img_name}"
with open(img_path, "wb") as f:
f.write(img_bytes)
print(f"✅ 保存图片:{img_path.name}")
saved_count += 1
except Exception as e:
print(f"❌ 保存图片 {key} 失败:{e}")
print(f"🖼️ 已保存 {saved_count} 张图片到 {output_dir}/")
def test_file_parse():
for file_path in FILES:
if not os.path.exists(file_path):
print(f"❌ 文件不存在:{file_path}")
return
file_entries = []
file_objects = []
for file_path in FILES:
path = Path(file_path)
f = open(file_path, 'rb')
content_type = 'application/pdf' if path.suffix.lower() == '.pdf' else 'image/jpeg'
file_entries.append(('files', (path.name, f, content_type)))
file_objects.append(f)
data = {}
for key, value in OPTIONS.items():
if value is not None:
if isinstance(value, (list, tuple)):
data[key] = json.dumps(value, ensure_ascii=False)
else:
data[key] = str(value)
try:
print("📤 正在发送请求到 MinerU API...")
response = requests.post(API_URL, data=data, files=file_entries)
print(f"📡 状态码:{response.status_code}")
if response.status_code == 200:
result = response.json()
print("✅ 解析成功!")
if "results" not in result:
print("❌ 缺少 'results' 字段")
print("返回:", json.dumps(result, indent=2, ensure_ascii=False))
return
results = result["results"]
for file_path in FILES:
file_key = get_file_key(file_path)
if file_key not in results:
print(f"❌ 找不到结果:{file_key},可用 keys: {list(results.keys())}")
continue
file_result = results[file_key]
if "md_content" in file_result:
save_md_content(file_result["md_content"], f"output_{file_key}.md")
else:
print(f"⚠️ 无 md_content")
if "images" in file_result and file_result["images"]:
save_images(file_result["images"], "images")
else:
print(f"🔍 无图片内容")
if "content_list" in file_result:
with open(f"content_list_{file_key}.json", "w", encoding="utf-8") as f:
json.dump(file_result["content_list"], f, indent=2, ensure_ascii=False)
print(f"📋 content_list 已保存")
else:
print("❌ 请求失败:")
try:
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except:
print(response.text)
except Exception as e:
print(f"🚨 异常:{e}")
finally:
for f in file_objects:
try:
f.close()
except:
pass
if __name__ == "__main__":
test_file_parse()