Marker PDF 转 Markdown¶
为什么要学 Marker¶
Marker 是一个高质量的 PDF 转 Markdown 工具,能够准确地将 PDF 文档(包括学术论文、技术文档、书籍等)转换为格式良好的 Markdown 文本。相比简单的文本提取工具,Marker 能够保留标题层级、代码块、表格、公式和列表等格式。对于构建 RAG 知识库、文档数字化和内容迁移来说,Marker 提供了最好的 PDF→Markdown 转换质量。
核心概念¶
| 概念 | 白话解释 | 用途 |
|---|---|---|
| Layout Detection | 版面检测 | 识别标题、正文、图表等区域 |
| OCR | 光学字符识别 | 从扫描件/图片中提取文字 |
| Table Recognition | 表格识别 | 将 PDF 中的表格转为 Markdown 表格 |
| Math OCR | 公式识别 | 将数学公式转为 LaTeX |
| Metadata | 元数据 | 提取文档标题、作者等信息 |
| Batch Processing | 批量处理 | 同时转换多个 PDF |
安装配置¶
安装¶
系统要求¶
- Python 3.9+
- 至少 4GB RAM(推荐 8GB+)
- GPU 可选但推荐(显著提速)
下载模型¶
快速上手¶
命令行使用¶
# 单个文件转换
marker_single input.pdf output_dir
# 指定输出格式
marker_single input.pdf output_dir --output_format markdown
# 批量转换目录下所有 PDF
marker output_dir --input_dir ./pdfs
# 带参数
marker_single paper.pdf ./output \
--languages "Chinese,English" \
--max_pages 50
Python API¶
from marker.converters.pdf import PdfConverter
from marker.models import create_model_dict
# 创建模型
models = create_model_dict()
# 创建转换器
converter = PdfConverter(artifact_dict=models)
# 转换
rendered = converter("paper.pdf")
# 获取 Markdown 文本
markdown_text = rendered.markdown
# 获取元数据
metadata = rendered.metadata
print(f"标题: {metadata.get('title', 'Unknown')}")
print(f"页数: {metadata.get('pages', 0)}")
# 保存
with open("output.md", "w", encoding="utf-8") as f:
f.write(markdown_text)
# 保存图片
for name, image in rendered.images.items():
image.save(f"images/{name}")
转换质量示例¶
PDF 原文:
┌─────────────────────────────┐
│ Chapter 3: Data Structures │ ← 标题
│ │
│ Python provides several │ ← 正文
│ built-in data structures: │
│ │
│ • Lists │ ← 列表
│ • Dictionaries │
│ • Sets │
│ │
│ | Name | Type | Mutable | │ ← 表格
│ |------|------|---------| │
│ | list | seq | Yes | │
└─────────────────────────────┘
Marker 输出:
# Chapter 3: Data Structures
Python provides several built-in data structures:
- Lists
- Dictionaries
- Sets
| Name | Type | Mutable |
|------|------|---------|
| list | seq | Yes |
进阶用法¶
批量处理优化¶
from marker.converters.pdf import PdfConverter
from marker.models import create_model_dict
from pathlib import Path
import json
models = create_model_dict()
converter = PdfConverter(artifact_dict=models)
input_dir = Path("./pdfs")
output_dir = Path("./markdown")
output_dir.mkdir(exist_ok=True)
results = []
for pdf_path in input_dir.glob("*.pdf"):
print(f"Converting: {pdf_path.name}")
try:
rendered = converter(str(pdf_path))
# 保存 Markdown
md_path = output_dir / f"{pdf_path.stem}.md"
md_path.write_text(rendered.markdown, encoding="utf-8")
# 保存图片
img_dir = output_dir / f"{pdf_path.stem}_images"
if rendered.images:
img_dir.mkdir(exist_ok=True)
for name, img in rendered.images.items():
img.save(img_dir / name)
results.append({
"file": pdf_path.name,
"status": "success",
"pages": rendered.metadata.get("pages", 0)
})
except Exception as e:
results.append({"file": pdf_path.name, "status": "error", "error": str(e)})
# 保存转换报告
with open(output_dir / "report.json", "w") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
配置参数调优¶
converter = PdfConverter(
artifact_dict=models,
config={
"languages": ["Chinese", "English"], # 文档语言
"force_ocr": False, # 强制 OCR(扫描件时启用)
"paginate_output": True, # 添加页码分隔
"extract_images": True, # 提取图片
"max_pages": None, # 最大页数限制
}
)
处理学术论文¶
# 学术论文通常包含:双栏排版、公式、引用、图表
rendered = converter("arxiv_paper.pdf")
# 公式会被转为 LaTeX
# $E = mc^2$
# $$\int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}$$
# 引用保持格式
# [1] Author et al., Title, Journal, 2024.
集成到 RAG Pipeline¶
from marker.converters.pdf import PdfConverter
from marker.models import create_model_dict
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 转换 PDF
models = create_model_dict()
converter = PdfConverter(artifact_dict=models)
rendered = converter("knowledge_base.pdf")
# 切片
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n## ", "\n### ", "\n\n", "\n", " "]
)
chunks = splitter.split_text(rendered.markdown)
# 存入向量库
from chromadb import Client
client = Client()
collection = client.create_collection("knowledge")
collection.add(
documents=chunks,
ids=[f"chunk_{i}" for i in range(len(chunks))]
)
后处理清洗¶
import re
def clean_markdown(text: str) -> str:
# 修复多余换行
text = re.sub(r'\n{3,}', '\n\n', text)
# 修复断行(PDF 中常见的行内断行)
text = re.sub(r'(?<=[a-z,])\n(?=[a-z])', ' ', text)
# 清理页眉页脚残留
text = re.sub(r'^\d+\s*$', '', text, flags=re.MULTILINE)
# 规范化标题
text = re.sub(r'^(#+)\s*(\d+\.?\s*)', r'\1 ', text, flags=re.MULTILINE)
return text.strip()
常见问题¶
Q: 中文 PDF 转换效果差?¶
- 设置
languages=["Chinese", "English"] - 扫描件启用
force_ocr=True - 确保安装了中文 OCR 模型
Q: 转换速度慢?¶
- 使用 GPU 加速(速度提升 5-10 倍)
- 限制页数
max_pages - 减少不需要的功能(如不提取图片)
- 批量处理使用
marker命令(自动并行)
Q: 表格识别不准确?¶
Marker 的表格识别依赖版面检测模型。对于复杂表格: - 尝试更高分辨率的 PDF - 后处理时手动修正 - 对关键表格使用专门的表格提取工具
Q: 与其他 PDF 转换工具对比?¶
- Marker:综合质量最好,保留格式
- PyMuPDF/pdfplumber:速度快但只提取原始文本
- Unstructured:更通用但 Markdown 质量不如 Marker
- Nougat:学术论文专精,公式最强
参考资源¶
- GitHub:https://github.com/VikParuchuri/marker
- 安装指南:https://github.com/VikParuchuri/marker#installation
- Surya OCR(底层组件):https://github.com/VikParuchuri/surya
- 基准测试:https://github.com/VikParuchuri/marker#benchmarks
- 相关工具:Nougat、GROBID