MarkItDown
MarkItDown 是微软开源的轻量级文档转换工具,可以将多种格式(Word、PowerPoint、Excel、PDF等)转换为Markdown格式,特别适合文档预处理和知识管理场景。
🌟 核心特性
- ✅ 多格式支持:支持DOCX、PPTX、XLSX、PDF、HTML等
- ✅ 轻量简洁:纯Python实现,无复杂依赖
- ✅ 易于集成:简单的API,易于集成到工作流
- ✅ 微软出品:官方维护,质量有保障
- ✅ 开源免费:MIT协议,可商用
- ✅ 保留格式:尽可能保留原文档的结构和格式
- ✅ 本地处理:无需上传文件,保护隐私
📦 安装与使用
快速安装
# 使用 pip 安装
pip install markitdown
# 从源码安装
git clone https://github.com/microsoft/markitdown.git
cd markitdown
pip install -e .
命令行使用
# 转换单个文件
markitdown document.docx
# 指定输出文件
markitdown document.docx -o output.md
# 转换多个文件
markitdown *.docx -o ./markdown/
# 批量转换目录
markitdown ./documents/ -o ./output/
Python API
from markitdown import MarkItDown
# 创建转换器
md = MarkItDown()
# 转换文档
result = md.convert("document.docx")
markdown_text = result.text_content
# 保存为Markdown文件
with open("output.md", "w", encoding="utf-8") as f:
f.write(markdown_text)
print(markdown_text)
🏗️ 技术架构
graph TB
A[输入文档] --> B{格式检测}
B -->|DOCX| C[python-docx]
B -->|PPTX| D[python-pptx]
B -->|XLSX| E[openpyxl]
B -->|PDF| F[PyPDF2]
B -->|HTML| G[BeautifulSoup]
C --> H[内容提取]
D --> H
E --> H
F --> H
G --> H
H --> I[格式转换]
I --> J[Markdown生成]
J --> K[输出文件]
支持的格式
| 格式 | 扩展名 | 支持度 | 说明 |
|---|---|---|---|
| Word | .docx | ⭐⭐⭐⭐⭐ | 完整支持 |
| PowerPoint | .pptx | ⭐⭐⭐⭐ | 支持文本和图片 |
| Excel | .xlsx | ⭐⭐⭐⭐ | 转为Markdown表格 |
| ⭐⭐⭐ | 基础文本提取 | ||
| HTML | .html | ⭐⭐⭐⭐⭐ | 完整支持 |
| 纯文本 | .txt | ⭐⭐⭐⭐⭐ | 直接转换 |
🎯 应用场景
1. Word文档转换
from markitdown import MarkItDown
def convert_word_to_markdown(docx_path, output_path):
"""将Word文档转换为Markdown"""
md = MarkItDown()
# 转换文档
result = md.convert(docx_path)
# 保存Markdown
with open(output_path, "w", encoding="utf-8") as f:
f.write(result.text_content)
# 提取元数据
metadata = {
"title": result.title,
"images": len(result.images),
"tables": len(result.tables)
}
return markdown_text, metadata
# 使用示例
text, meta = convert_word_to_markdown("report.docx", "report.md")
print(f"转换完成,包含 {meta['images']} 张图片,{meta['tables']} 个表格")
2. PowerPoint转换
def convert_ppt_to_markdown(pptx_path, output_path):
"""将PPT转换为Markdown"""
md = MarkItDown()
result = md.convert(pptx_path)
# PPT会按幻灯片组织内容
markdown = result.text_content
# 保存
with open(output_path, "w", encoding="utf-8") as f:
f.write(markdown)
return markdown
# 转换演示文稿
markdown = convert_ppt_to_markdown("presentation.pptx", "slides.md")
3. Excel表格转换
def convert_excel_to_markdown(xlsx_path, output_path):
"""将Excel转换为Markdown表格"""
md = MarkItDown()
result = md.convert(xlsx_path)
# Excel的每个工作表会转为独立的表格
markdown = result.text_content
with open(output_path, "w", encoding="utf-8") as f:
f.write(markdown)
return markdown
# 转换电子表格
markdown = convert_excel_to_markdown("data.xlsx", "tables.md")
4. PDF文档转换
def convert_pdf_to_markdown(pdf_path, output_path):
"""将PDF转换为Markdown"""
md = MarkItDown()
try:
result = md.convert(pdf_path)
markdown = result.text_content
with open(output_path, "w", encoding="utf-8") as f:
f.write(markdown)
return markdown
except Exception as e:
print(f"PDF转换失败: {e}")
return None
# 转换PDF
markdown = convert_pdf_to_markdown("document.pdf", "document.md")
5. 批量文档转换
from pathlib import Path
import json
def batch_convert_documents(input_dir, output_dir):
"""批量转换文档"""
md = MarkItDown()
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
# 支持的文件扩展名
extensions = ['.docx', '.pptx', '.xlsx', '.pdf', '.html']
results = []
for ext in extensions:
for doc_file in input_path.glob(f"*{ext}"):
try:
print(f"转换: {doc_file.name}")
# 转换文档
result = md.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.text_content)
results.append({
"file": doc_file.name,
"status": "success",
"output": md_file.name,
"size": len(result.text_content)
})
print(f"完成: {doc_file.name} -> {md_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 / "conversion_report.json"
with open(report_file, "w", encoding="utf-8") as f:
json.dump(results, f, indent=2, ensure_ascii=False)
return results
# 批量转换
results = batch_convert_documents("./documents", "./markdown")
print(f"转换完成,成功: {sum(1 for r in results if r['status']=='success')} 个")
6. 自定义转换选项
from markitdown import MarkItDown, ConversionOptions
def convert_with_options(file_path, output_path):
"""使用自定义选项转换"""
# 创建转换选项
options = ConversionOptions(
extract_images=True, # 提取图片
image_dir="./images", # 图片保存目录
preserve_tables=True, # 保留表格格式
include_metadata=True, # 包含元数据
heading_style="atx" # 标题样式 (atx/setext)
)
# 创建转换器
md = MarkItDown(options=options)
# 转换
result = md.convert(file_path)
# 保存
with open(output_path, "w", encoding="utf-8") as f:
f.write(result.text_content)
# 保存提取的图片
for i, img in enumerate(result.images):
img_path = f"./images/image_{i}.png"
img.save(img_path)
return result
🔧 高级配置
图片处理
from markitdown import MarkItDown
md = MarkItDown(
extract_images=True, # 提取图片
image_dir="./images", # 图片目录
image_format="png", # 图片格式
max_image_size=(1920, 1080) # 最大尺寸
)
result = md.convert("document.docx")
# 图片会保存到指定目录,Markdown中使用相对路径引用
表格格式化
from markitdown import MarkItDown
md = MarkItDown(
table_format="github", # github/simple/grid
preserve_table_alignment=True, # 保留对齐方式
table_max_width=100 # 表格最大宽度
)
result = md.convert("spreadsheet.xlsx")
自定义输出格式
from markitdown import MarkItDown
md = MarkItDown(
heading_style="atx", # atx (###) 或 setext (===)
bullet_char="-", # 列表符号 (-, *, +)
code_block_style="fenced", # fenced (```) 或 indented
emphasis_style="asterisk" # asterisk (*) 或 underscore (_)
)
result = md.convert("document.docx")
📊 性能对比
| 工具 | 速度 | DOCX支持 | PDF支持 | 易用性 | 依赖 |
|---|---|---|---|---|---|
| MarkItDown | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 少 |
| Pandoc | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | 多 |
| mammoth | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ❌ | ⭐⭐⭐⭐ | 少 |
| pdf2md | ⭐⭐⭐ | ❌ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 少 |
💡 最佳实践
-
文件预处理
# 检查文件是否存在和格式
from pathlib import Path
def safe_convert(file_path):
path = Path(file_path)
if not path.exists():
raise FileNotFoundError(f"文件不存在: {file_path}")
if path.suffix not in ['.docx', '.pptx', '.xlsx', '.pdf']:
raise ValueError(f"不支持的格式: {path.suffix}")
md = MarkItDown()
return md.convert(str(path)) -
错误处理
def robust_convert(file_path, output_path):
"""带错误处理的转换"""
try:
md = MarkItDown()
result = md.convert(file_path)
with open(output_path, "w", encoding="utf-8") as f:
f.write(result.text_content)
return True, "转换成功"
except Exception as e:
return False, f"转换失败: {str(e)}" -
后处理优化
def post_process_markdown(markdown_text):
"""后处理Markdown文本"""
# 移除多余的空行
lines = markdown_text.split('\n')
cleaned = []
prev_empty = False
for line in lines:
if line.strip():
cleaned.append(line)
prev_empty = False
elif not prev_empty:
cleaned.append(line)
prev_empty = True
return '\n'.join(cleaned) -
大文件处理
def convert_large_file(file_path, chunk_size=1000000):
"""处理大文件"""
import os
file_size = os.path.getsize(file_path)
if file_size > 100 * 1024 * 1024: # 100MB
print("警告:文件较大,可能需要较长时间")
md = MarkItDown()
result = md.convert(file_path)
return result
🔍 常见问题
Q1: 如何处理包含图片的文档?
md = MarkItDown(extract_images=True, image_dir="./images")
result = md.convert("document.docx")
# 图片会自动提取到指定目录
Q2: 如何保持表格格式?
md = MarkItDown(
table_format="github", # 使用GitHub风格表格
preserve_table_alignment=True # 保留对齐
)
Q3: 转换失败怎么办?
# 尝试不同的选项
md = MarkItDown(strict_mode=False) # 宽松模式
result = md.convert(file_path)
📚 资源链接
- GitHub: https://github.com/microsoft/markitdown
- PyPI: https://pypi.org/project/markitdown/
- 文档: https://microsoft.github.io/markitdown/
- 示例: https://github.com/microsoft/markitdown/tree/main/examples
⚠️ 注意事项
- PDF转换依赖文本层,扫描版PDF效果较差
- 复杂格式可能无法完全保留
- 大文件转换可能需要较多内存
- 建议处理前备份原文件
- 某些Office特殊格式可能不支持
🆚 适用场景
选择 MarkItDown 当:
- 需要快速转换Office文档
- 追求简单易用
- 依赖较少的环境
- 批量处理文档
- 微软Office格式为主
选择其他工具当:
- 需要更复杂的转换 → Pandoc
- 只处理Word文档 → mammoth
- PDF为主 → Marker/MinerU
- 需要OCR功能 → PaddleOCR系列
🔄 更新日志
- 2024.06: v1.2 - 改进PDF支持
- 2024.03: v1.1 - 添加图片提取
- 2023.12: v1.0 - 首次发布
💻 与其他工具集成
与RAG系统集成
def prepare_documents_for_rag(input_dir):
"""为RAG准备文档"""
md = MarkItDown()
documents = []
for file in Path(input_dir).glob("*.docx"):
result = md.convert(str(file))
documents.append({
"content": result.text_content,
"source": file.name,
"metadata": {
"title": result.title,
"format": "docx"
}
})
return documents
与版本控制集成
def convert_and_commit(docx_path):
"""转换后提交到Git"""
md = MarkItDown()
result = md.convert(docx_path)
md_path = docx_path.replace('.docx', '.md')
with open(md_path, 'w', encoding='utf-8') as f:
f.write(result.text_content)
# Git操作
import subprocess
subprocess.run(['git', 'add', md_path])
subprocess.run(['git', 'commit', '-m', f'Update {md_path}'])