跳到主要内容

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表格
PDF.pdf⭐⭐⭐基础文本提取
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⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

💡 最佳实践

  1. 文件预处理

    # 检查文件是否存在和格式
    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))
  2. 错误处理

    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)}"
  3. 后处理优化

    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)
  4. 大文件处理

    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)

📚 资源链接

⚠️ 注意事项

  • 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}'])