5分钟学会MinerU API调用:轻松搞定扫描件文字识别与内容总结

1. 快速上手:为什么你需要MinerU?

想象一下这个场景:你收到一份PDF格式的合同扫描件,需要快速提取关键条款;或者你有一堆学术论文截图,想要快速了解每篇的核心观点。传统方法是什么?要么手动打字,要么用通用OCR工具识别,然后自己整理总结——整个过程耗时耗力,还容易出错。

这就是MinerU智能文档理解服务要解决的问题。它就像一个专门处理文档的AI助手,你给它一张图片,它不仅能准确识别上面的文字,还能理解内容、总结要点,甚至回答你的问题。

最吸引人的三点

  1. 轻量快速:1.2B的小模型,在普通电脑CPU上就能跑,响应速度飞快
  2. 文档专精:专门针对文档场景优化,处理表格、公式、复杂排版比通用工具强得多
  3. 简单易用:提供标准的API接口,几行代码就能集成到你的系统里

接下来,我会带你用5分钟时间,从零开始学会怎么调用MinerU的API,让你也能轻松实现文档自动化处理。

2. 准备工作:启动服务与检查状态

2.1 启动MinerU服务

如果你已经在CSDN星图平台找到了MinerU镜像,启动过程非常简单:

  1. 点击“部署”按钮,等待镜像启动完成
  2. 系统会提供一个访问地址,通常是 http://localhost:8080 或类似的URL
  3. 点击HTTP访问按钮,就能看到MinerU的Web界面了

2.2 验证服务是否正常

在开始写代码之前,先确认服务已经正常运行。打开命令行工具,输入:

curl http://localhost:8080/health

如果看到这样的返回结果,说明一切正常:

{"status":"ok","model":"MinerU2.5-2509-1.2B"}

如果返回错误或者超时,可能需要检查:

  • 服务是否完全启动(等待1-2分钟再试)
  • 网络连接是否正常
  • 端口号是否正确

3. 核心API调用:从图片到文字的魔法

3.1 理解API的工作方式

MinerU的API设计得很直观,你只需要做两件事:

  1. 把图片传给它
  2. 告诉它你想做什么

它支持多种指令,比如:

  • “请提取图中的所有文字”
  • “总结这份文档的主要内容”
  • “表格里的数据是什么?”
  • “这段代码是什么意思?”

3.2 最简单的Python调用示例

让我们从一个完整的例子开始。假设你有一张文档截图 document.png,想要提取上面的文字:

import requests
import base64
import json

# 第一步:准备图片
def encode_image_to_base64(image_path):
    """把图片转换成base64编码的字符串"""
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

# 第二步:构建请求
image_base64 = encode_image_to_base64("document.png")

payload = {
    "model": "mineru",
    "messages": [
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "image_url": f"data:image/jpeg;base64,{image_base64}"
                },
                {
                    "type": "text", 
                    "text": "请将图中的文字完整提取出来"
                }
            ]
        }
    ],
    "stream": False
}

# 第三步:发送请求
response = requests.post(
    "http://localhost:8080/v1/chat/completions",
    headers={"Content-Type": "application/json"},
    data=json.dumps(payload),
    timeout=30
)

# 第四步:处理结果
if response.status_code == 200:
    result = response.json()
    extracted_text = result['choices'][0]['message']['content']
    print("提取到的文字:")
    print(extracted_text)
else:
    print(f"请求失败:{response.status_code}")
    print(response.text)

运行这段代码,你就能看到图片里的文字被完整地提取出来了。是不是很简单?

4. 实战应用:三种常见场景的完整解决方案

4.1 场景一:扫描件文字提取(合同、报告、票据)

很多公司需要处理大量的扫描文档,比如合同、财务报表、发票等。手动录入不仅慢,还容易出错。

优化后的代码示例

class DocumentProcessor:
    def __init__(self, api_url="http://localhost:8080"):
        self.api_url = api_url
        
    def extract_text_from_scanned_doc(self, image_path, output_file=None):
        """
        从扫描件中提取文字,支持保存到文件
        
        参数:
            image_path: 图片路径
            output_file: 可选,保存提取结果的文本文件路径
        """
        # 编码图片
        with open(image_path, "rb") as f:
            image_data = base64.b64encode(f.read()).decode('utf-8')
        
        # 构建请求
        request_data = {
            "model": "mineru",
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {"type": "image", "image_url": f"data:image/jpeg;base64,{image_data}"},
                        {"type": "text", "text": "请准确提取图片中的所有文字,保持原文格式"}
                    ]
                }
            ]
        }
        
        # 发送请求
        response = requests.post(
            f"{self.api_url}/v1/chat/completions",
            json=request_data,
            timeout=60  # 给大文件多一点时间
        )
        
        if response.status_code == 200:
            text_content = response.json()['choices'][0]['message']['content']
            
            # 如果需要保存到文件
            if output_file:
                with open(output_file, 'w', encoding='utf-8') as f:
                    f.write(text_content)
                print(f"文字已保存到:{output_file}")
            
            return text_content
        else:
            print(f"提取失败:{response.status_code}")
            return None

# 使用示例
processor = DocumentProcessor()

# 提取合同扫描件
contract_text = processor.extract_text_from_scanned_doc(
    "contract_scan.jpg", 
    output_file="contract_text.txt"
)

# 提取发票
invoice_text = processor.extract_text_from_scanned_doc("invoice.png")

实用技巧

  • 对于模糊的扫描件,可以先使用图片处理库(如PIL)进行锐化和对比度调整
  • 如果文档有多页,可以每页单独处理,然后合并结果
  • 重要的合同或法律文件,建议人工核对关键条款

4.2 场景二:文档内容总结(论文、文章、报告)

当你需要快速了解一份长文档的核心内容时,让MinerU帮你总结是最省时的方法。

智能总结代码示例

def summarize_document(image_path, summary_type="brief"):
    """
    总结文档内容
    
    参数:
        image_path: 文档图片路径
        summary_type: 总结类型,可选 "brief"(简短), "detailed"(详细), "bullet"(要点)
    """
    
    # 根据类型选择不同的提示词
    prompts = {
        "brief": "用一段话总结这份文档的核心内容",
        "detailed": "详细总结这份文档的主要观点和结论",
        "bullet": "用要点列表的形式总结这份文档的关键信息"
    }
    
    prompt = prompts.get(summary_type, "总结这份文档的内容")
    
    # 编码图片
    with open(image_path, "rb") as f:
        image_base64 = base64.b64encode(f.read()).decode('utf-8')
    
    # 发送总结请求
    response = requests.post(
        "http://localhost:8080/v1/chat/completions",
        json={
            "model": "mineru",
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {"type": "image", "image_url": f"data:image/jpeg;base64,{image_base64}"},
                        {"type": "text", "text": prompt}
                    ]
                }
            ]
        }
    )
    
    if response.status_code == 200:
        summary = response.json()['choices'][0]['message']['content']
        return summary
    else:
        return f"总结失败:{response.status_code}"

# 使用示例
# 简短总结学术论文
paper_summary = summarize_document("research_paper.png", "brief")
print("论文核心内容:")
print(paper_summary)

# 详细总结业务报告
report_summary = summarize_document("business_report.png", "detailed")
print("\n报告详细总结:")
print(report_summary)

# 要点总结会议纪要
meeting_summary = summarize_document("meeting_minutes.png", "bullet")
print("\n会议要点:")
print(meeting_summary)

让总结更准确的小技巧

  1. 指定总结重点:比如“总结技术方案部分”或“重点关注数据结果”
  2. 控制总结长度:添加“控制在200字以内”或“分三点说明”
  3. 提取特定信息:比如“找出所有的日期和责任人”

4.3 场景三:表格数据提取(财务报表、数据报表)

表格是文档中最有价值也最难处理的部分。MinerU在这方面表现特别出色。

表格提取与结构化代码

def extract_table_data(image_path, table_description=None):
    """
    提取图片中的表格数据
    
    参数:
        image_path: 包含表格的图片路径
        table_description: 可选,表格描述,如“提取销售数据表格”
    """
    
    # 准备提示词
    if table_description:
        prompt = f"{table_description},以表格形式返回数据"
    else:
        prompt = "提取图片中的表格数据,以清晰的表格格式返回"
    
    # 处理图片
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode('utf-8')
    
    # 发送请求
    response = requests.post(
        "http://localhost:8080/v1/chat/completions",
        json={
            "model": "mineru", 
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {"type": "image", "image_url": f"data:image/jpeg;base64,{image_data}"},
                        {"type": "text", "text": prompt}
                    ]
                }
            ]
        },
        timeout=45  # 表格处理可能需要更长时间
    )
    
    if response.status_code == 200:
        table_data = response.json()['choices'][0]['message']['content']
        
        # 尝试解析为结构化数据
        import re
        
        # 查找表格数据
        rows = []
        for line in table_data.split('\n'):
            if '|' in line and '---' not in line:  # 跳过分隔线
                # 清理并分割单元格
                cells = [cell.strip() for cell in line.split('|') if cell.strip()]
                if cells:
                    rows.append(cells)
        
        return {
            "raw_text": table_data,
            "structured_rows": rows if rows else None
        }
    else:
        return {"error": f"请求失败:{response.status_code}"}

# 使用示例
# 提取财务报表
financial_table = extract_table_data("financial_statement.png", "提取利润表数据")
print("表格数据:")
print(financial_table["raw_text"])

if financial_table["structured_rows"]:
    print("\n结构化数据:")
    for row in financial_table["structured_rows"]:
        print(row)

处理复杂表格的建议

  1. 明确指定表格:如果图片中有多个表格,用“左上角的表格”或“标题为'销售数据'的表格”来指定
  2. 要求特定格式:添加“用CSV格式返回”或“用Markdown表格格式”
  3. 分批处理:对于特别大的表格,可以分区域截图处理

5. 高级技巧与问题解决

5.1 批量处理多个文档

当你需要处理大量文档时,单个处理效率太低。这里提供一个批量处理的方案:

import os
from concurrent.futures import ThreadPoolExecutor, as_completed

def batch_process_documents(image_folder, output_folder, process_type="extract"):
    """
    批量处理文件夹中的所有图片文档
    
    参数:
        image_folder: 包含图片的文件夹路径
        output_folder: 输出结果文件夹
        process_type: 处理类型,extract(提取) 或 summarize(总结)
    """
    
    # 创建输出文件夹
    os.makedirs(output_folder, exist_ok=True)
    
    # 获取所有图片文件
    image_files = []
    for file in os.listdir(image_folder):
        if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):
            image_files.append(os.path.join(image_folder, file))
    
    print(f"找到 {len(image_files)} 个图片文件")
    
    def process_single_file(image_path):
        """处理单个文件"""
        try:
            filename = os.path.basename(image_path)
            output_file = os.path.join(output_folder, f"{os.path.splitext(filename)[0]}.txt")
            
            if process_type == "extract":
                result = extract_text_from_scanned_doc(image_path)
            else:
                result = summarize_document(image_path)
            
            if result:
                with open(output_file, 'w', encoding='utf-8') as f:
                    f.write(result)
                return filename, True
            else:
                return filename, False
                
        except Exception as e:
            print(f"处理 {image_path} 时出错:{e}")
            return os.path.basename(image_path), False
    
    # 使用线程池并发处理
    results = []
    with ThreadPoolExecutor(max_workers=3) as executor:  # 控制并发数,避免服务器压力过大
        future_to_file = {executor.submit(process_single_file, img): img for img in image_files}
        
        for future in as_completed(future_to_file):
            filename, success = future.result()
            results.append((filename, success))
    
    # 统计结果
    success_count = sum(1 for _, success in results if success)
    print(f"处理完成:成功 {success_count}/{len(image_files)} 个文件")
    
    return results

# 使用示例
# 批量提取文字
batch_results = batch_process_documents(
    image_folder="./scanned_docs",
    output_folder="./extracted_texts",
    process_type="extract"
)

# 批量总结内容
summary_results = batch_process_documents(
    image_folder="./reports",
    output_folder="./summaries", 
    process_type="summarize"
)

5.2 常见问题与解决方案

在实际使用中,你可能会遇到一些问题。这里是一些常见问题的解决方法:

问题现象可能原因解决方案
返回空内容或乱码图片质量太差、文字太小1. 确保图片清晰度至少300dpi
2. 调整图片对比度
3. 尝试黑白二值化处理
请求超时图片太大、服务器忙1. 压缩图片到2MB以内
2. 增加超时时间到60秒
3. 分批处理大文件
识别结果不准确复杂排版、特殊字体1. 使用更明确的指令,如"识别第三段文字"
2. 对图片进行预处理
3. 分区域截图识别
内存不足同时处理太多请求1. 减少并发数量
2. 增加服务器内存
3. 使用队列顺序处理

图片预处理代码示例

from PIL import Image, ImageEnhance
import cv2
import numpy as np

def preprocess_image_for_ocr(image_path, output_path=None):
    """
    预处理图片,提高OCR识别准确率
    """
    # 方法1:使用PIL调整对比度和锐度
    img = Image.open(image_path)
    
    # 转换为灰度图
    if img.mode != 'L':
        img = img.convert('L')
    
    # 增强对比度
    enhancer = ImageEnhance.Contrast(img)
    img = enhancer.enhance(2.0)  # 增加对比度
    
    # 增强锐度
    enhancer = ImageEnhance.Sharpness(img)
    img = enhancer.enhance(2.0)
    
    # 方法2:使用OpenCV进行二值化(备选)
    # img_cv = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    # _, img_binary = cv2.threshold(img_cv, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    
    if output_path:
        img.save(output_path)
        return output_path
    else:
        # 保存到临时文件
        temp_path = "temp_processed.png"
        img.save(temp_path)
        return temp_path

# 使用预处理后的图片
processed_image = preprocess_image_for_ocr("blurry_document.jpg")
result = extract_text_from_scanned_doc(processed_image)

5.3 性能优化建议

  1. 连接复用:如果需要频繁调用API,使用Session可以提升性能
import requests

# 创建会话,复用TCP连接
session = requests.Session()

# 在循环中使用同一个session
for image_path in image_list:
    response = session.post(api_url, json=payload, timeout=30)
  1. 异步处理:对于大量文档,使用异步可以大幅提升处理速度
import aiohttp
import asyncio

async def async_extract_text(session, image_path):
    """异步提取文字"""
    # 编码图片
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode('utf-8')
    
    payload = {
        "model": "mineru",
        "messages": [{
            "role": "user",
            "content": [
                {"type": "image", "image_url": f"data:image/jpeg;base64,{image_data}"},
                {"type": "text", "text": "提取文字"}
            ]
        }]
    }
    
    async with session.post(api_url, json=payload) as response:
        return await response.json()

# 批量异步处理
async def process_batch_async(image_paths):
    async with aiohttp.ClientSession() as session:
        tasks = [async_extract_text(session, path) for path in image_paths]
        results = await asyncio.gather(*tasks)
        return results
  1. 结果缓存:对于相同的文档,避免重复处理
import hashlib
import json
from pathlib import Path

class CachedMinerUClient:
    def __init__(self, cache_dir="./cache"):
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(exist_ok=True)
    
    def get_cache_key(self, image_path, prompt):
        """生成缓存键"""
        # 使用文件内容和提示词生成唯一键
        with open(image_path, "rb") as f:
            file_hash = hashlib.md5(f.read()).hexdigest()
        
        prompt_hash = hashlib.md5(prompt.encode()).hexdigest()
        return f"{file_hash}_{prompt_hash}.json"
    
    def process_with_cache(self, image_path, prompt):
        """带缓存的处理"""
        cache_key = self.get_cache_key(image_path, prompt)
        cache_file = self.cache_dir / cache_key
        
        # 检查缓存
        if cache_file.exists():
            print(f"使用缓存结果:{cache_key}")
            with open(cache_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        
        # 调用API
        result = self.call_mineru_api(image_path, prompt)
        
        # 保存到缓存
        with open(cache_file, 'w', encoding='utf-8') as f:
            json.dump(result, f, ensure_ascii=False, indent=2)
        
        return result

6. 总结

6.1 核心要点回顾

通过这5分钟的学习,你应该已经掌握了MinerU API调用的核心技能:

  1. 基础调用很简单:只需要准备图片、构建请求、发送请求、处理结果四步
  2. 应用场景广泛:文字提取、内容总结、表格识别都能轻松搞定
  3. 代码可复用:本文提供的代码示例可以直接用在你的项目中
  4. 性能足够好:在普通电脑上就能快速运行,适合各种规模的应用

6.2 最佳实践建议

根据我的使用经验,给你几个实用建议:

对于新手

  • 先从清晰的文档图片开始,熟悉基本流程
  • 使用简单的指令,比如“提取文字”或“总结内容”
  • 逐步尝试更复杂的需求,比如表格提取或多轮对话

对于项目集成

  • 一定要添加错误处理和重试机制
  • 考虑使用异步处理提升批量任务效率
  • 对于重要文档,建议保留人工审核环节

性能优化

  • 图片大小控制在2MB以内
  • 复杂文档可以分区域处理
  • 使用连接池和缓存减少重复请求

6.3 下一步学习方向

如果你已经掌握了基础调用,可以进一步探索:

  1. 多轮对话:基于之前的识别结果继续提问,比如“刚才那个表格里,第三行数据是什么?”
  2. 复杂指令:尝试更具体的需求,如“提取所有加粗的文字”或“找出文档中的日期和金额”
  3. 系统集成:将MinerU集成到你的OA系统、知识库或自动化流程中
  4. 自定义处理:结合其他工具,比如将提取的文字自动翻译、分类或生成报告

MinerU最吸引人的地方在于它的平衡性——既有不错的识别准确率,又保持了轻量和快速的特点。对于大多数文档处理需求来说,它都是一个性价比很高的选择。

现在,你可以开始用这些代码解决实际的文档处理问题了。从最简单的文字提取开始,逐步尝试更复杂的应用场景。记住,最好的学习方式就是动手实践。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

更多推荐