Docling
Docling 是 IBM Research 开源的企业级文档解析工具,专注于将各类文档(PDF、Word、PowerPoint等)转换为结构化格式,特别适合企业知识管理和RAG应用场景。
🌟 核心特性
- ✅ 多格式支持:PDF、DOCX、PPTX、HTML等多种格式
- ✅ 结构化输出:JSON、Markdown、DocBook等格式
- ✅ 企业级质量:高准确率,适合生产环境
- ✅ 版面分析:精确识别文档结构和层级
- ✅ 表格提取:高质量的表格识别和转换
- ✅ 元数据提取:提取作者、标题、日期等元信息
- ✅ 批量处理:支持大规模文档批处理
- ✅ 可扩展性:插件化架构,易于扩展
📦 安装与使用
快速安装
# 使用 pip 安装
pip install docling
# 安装完整版本(包含OCR)
pip install docling[ocr]
# 从源码安装
git clone https://github.com/DS4SD/docling.git
cd docling
pip install -e .
命令行使用
# 转换单个文档
docling convert document.pdf
# 指定输出格式
docling convert document.pdf --format markdown
# 批量转换
docling convert ./documents/*.pdf --output ./output
# 提取元数据
docling extract document.pdf --metadata
Python API
from docling import DocumentConverter
# 创建转换器
converter = DocumentConverter()
# 转换PDF
result = converter.convert("document.pdf")
# 获取Markdown
markdown = result.document.export_to_markdown()
print(markdown)
# 获取JSON
json_output = result.document.export_to_json()
# 获取文档结构
for element in result.document.elements:
print(f"类型: {element.type}, 内容: {element.text[:50]}")
🏗️ 技术架构
graph TB
A[输入文档] --> B{格式判断}
B -->|PDF| C[PDF解析器]
B -->|DOCX| D[DOCX解析器]
B -->|PPTX| E[PPTX解析器]
C --> F[版面分析]
D --> F
E --> F
F --> G[元素识别]
G --> H[结构化组装]
H --> I[格式转换]
I --> J[输出结果]
G -->|文本/标题/段落| G1[文本元素]
G -->|表格| G2[表格元素]
G -->|图片| G3[图片元素]
G -->|列表| G4[列表元素]
核心组件
- 解析器层: 支持多种文档格式的底层解析
- 分析层: 版面分析和结构识别
- 转换层: 格式转换和输出生成
- 扩展层: 插件和自定义处理
🎯 应用场景
1. 企业知识库构建
from docling import DocumentConverter
import json
def build_knowledge_base(doc_path):
"""构建企业知识库"""
converter = DocumentConverter()
result = converter.convert(doc_path)
# 提取结构化信息
knowledge = {
"title": result.document.metadata.get("title"),
"author": result.document.metadata.get("author"),
"date": result.document.metadata.get("date"),
"content": [],
"tables": [],
"images": []
}
# 按类型组织内容
for element in result.document.elements:
if element.type == "heading":
knowledge["content"].append({
"type": "section",
"level": element.level,
"title": element.text
})
elif element.type == "paragraph":
knowledge["content"].append({
"type": "text",
"content": element.text
})
elif element.type == "table":
knowledge["tables"].append({
"data": element.to_dataframe().to_dict(),
"caption": element.caption
})
elif element.type == "image":
knowledge["images"].append({
"path": element.image_path,
"caption": element.caption
})
return knowledge
2. RAG数据准备
from docling import DocumentConverter
def prepare_rag_documents(doc_path, chunk_size=500):
"""为RAG准备文档数据"""
converter = DocumentConverter()
result = converter.convert(doc_path)
chunks = []
current_chunk = ""
current_metadata = {}
for element in result.document.elements:
# 按标题分块
if element.type == "heading":
if current_chunk:
chunks.append({
"text": current_chunk,
"metadata": current_metadata.copy()
})
current_chunk = f"# {element.text}\n\n"
current_metadata = {
"section": element.text,
"level": element.level
}
# 添加内容
elif element.type == "paragraph":
current_chunk += element.text + "\n\n"
# 达到块大小限制
if len(current_chunk) >= chunk_size:
chunks.append({
"text": current_chunk,
"metadata": current_metadata.copy()
})
current_chunk = ""
# 添加最后一块
if current_chunk:
chunks.append({
"text": current_chunk,
"metadata": current_metadata
})
return chunks
3. 文档对比分析
from docling import DocumentConverter
from difflib import SequenceMatcher
def compare_documents(doc1_path, doc2_path):
"""对比两个文档"""
converter = DocumentConverter()
# 转换两个文档
doc1 = converter.convert(doc1_path)
doc2 = converter.convert(doc2_path)
# 提取文本
text1 = doc1.document.export_to_text()
text2 = doc2.document.export_to_text()
# 计算相似度
similarity = SequenceMatcher(None, text1, text2).ratio()
# 结构对比
structure_diff = {
"doc1_sections": len([e for e in doc1.document.elements if e.type == "heading"]),
"doc2_sections": len([e for e in doc2.document.elements if e.type == "heading"]),
"doc1_tables": len([e for e in doc1.document.elements if e.type == "table"]),
"doc2_tables": len([e for e in doc2.document.elements if e.type == "table"]),
}
return {
"text_similarity": similarity,
"structure_diff": structure_diff
}
4. 批量文档处理
from docling import DocumentConverter
from pathlib import Path
import json
def batch_process_documents(input_dir, output_dir):
"""批量处理文档"""
converter = DocumentConverter()
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
# 支持的文件格式
patterns = ["*.pdf", "*.docx", "*.pptx"]
results = []
for pattern in patterns:
for doc_file in input_path.glob(pattern):
try:
print(f"处理: {doc_file.name}")
# 转换文档
result = converter.convert(str(doc_file))
# 保存Markdown
md_file = output_path / f"{doc_file.stem}.md"
with open(md_file, "w", encoding="utf-8") as f:
f.write(result.document.export_to_markdown())
# 保存JSON元数据
meta_file = output_path / f"{doc_file.stem}_meta.json"
with open(meta_file, "w", encoding="utf-8") as f:
json.dump(result.document.metadata, f, indent=2)
results.append({
"file": doc_file.name,
"status": "success",
"pages": result.document.metadata.get("pages", 0)
})
print(f"完成: {doc_file.name}")
except Exception as e:
results.append({
"file": doc_file.name,
"status": "error",
"error": str(e)
})
print(f"错误 {doc_file.name}: {e}")
# 保存处理报告
report_file = output_path / "processing_report.json"
with open(report_file, "w", encoding="utf-8") as f:
json.dump(results, f, indent=2)
return results
🔧 高级配置
自定义转换器
from docling import DocumentConverter
from docling.datamodel import ConversionOptions
# 创建自定义配置
options = ConversionOptions(
# PDF配置
pdf_backend="pdfium", # pdfium/pypdfium2/pdfplumber
extract_images=True,
extract_tables=True,
# OCR配置
ocr_enabled=True,
ocr_language="chi_sim+eng", # 中英文OCR
# 表格配置
table_parser="camelot", # camelot/tabula
table_areas="stream", # stream/lattice
# 输出配置
preserve_layout=True,
include_metadata=True
)
# 使用自定义配置
converter = DocumentConverter(options=options)
result = converter.convert("document.pdf")
表格处理
def extract_all_tables(doc_path):
"""提取所有表格"""
converter = DocumentConverter()
result = converter.convert(doc_path)
tables = []
for element in result.document.elements:
if element.type == "table":
# 转为DataFrame
df = element.to_dataframe()
tables.append({
"page": element.page,
"caption": element.caption,
"data": df,
"markdown": element.to_markdown(),
"html": element.to_html()
})
return tables
插件扩展
from docling import DocumentConverter
from docling.plugins import Plugin
class CustomPlugin(Plugin):
"""自定义处理插件"""
def process_element(self, element):
"""处理每个元素"""
if element.type == "paragraph":
# 自定义段落处理
element.text = element.text.strip()
return element
# 注册插件
converter = DocumentConverter()
converter.register_plugin(CustomPlugin())
result = converter.convert("document.pdf")
📊 性能对比
| 特性 | Docling | MinerU | Marker | PyMuPDF |
|---|---|---|---|---|
| 多格式支持 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 结构化输出 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 企业级质量 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| 处理速度 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 易用性 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
💡 最佳实践
-
文档预处理
# 检查文档质量
result = converter.convert("document.pdf")
quality_score = result.metadata.get("quality_score", 0)
if quality_score < 0.7:
# 启用OCR
converter.options.ocr_enabled = True
result = converter.convert("document.pdf") -
内存优化
# 流式处理大文档
converter = DocumentConverter(streaming=True)
for page_result in converter.convert_stream("large_doc.pdf"):
process_page(page_result)
# 逐页处理,减少内存占用 -
错误处理
from docling.exceptions import ConversionError
try:
result = converter.convert("document.pdf")
except ConversionError as e:
print(f"转换失败: {e}")
# 降级处理
result = fallback_conversion("document.pdf") -
输出格式选择
# 根据用途选择格式
markdown = result.document.export_to_markdown() # 文档展示
json_data = result.document.export_to_json() # 数据分析
docbook = result.document.export_to_docbook() # 出版流程
📚 资源链接
- GitHub: https://github.com/DS4SD/docling
- 文档: https://ds4sd.github.io/docling/
- 论文: https://arxiv.org/abs/2408.09869
- Demo: https://huggingface.co/spaces/DS4SD/docling
⚠️ 注意事项
- 首次运行会下载必要的模型
- OCR功能需要额外安装tesseract
- 大文件处理可能需要较多内存
- 某些格式需要安装额外依赖
- 商业使用需注意license
🆚 适用场景
选择 Docling 当:
- 需要处理多种文档格式
- 构建企业级知识管理系统
- 需要高质量的结构化输出
- 准备RAG应用的数据
- 需要可靠的生产环境解决方案
选择其他工具当:
- 只处理PDF → Marker/MinerU
- 追求极致速度 → Marker
- 需要最高准确率 → MinerU
- 简单场景 → PyMuPDF
🔄 更新日志
- 2024.08: v1.0.0 - 正式发布
- 2024.06: Beta版本 - 添加PPTX支持
- 2024.04: Alpha版本 - 首次公开