MarkItDown:把 Office 文档与网页一键转成 Markdown 的微软开源工具
MarkItDown 是微软开源的轻量 Python 工具,用于把各种文件转换成 Markdown,供大模型和文本分析管线使用。它最接近 textract,但专注于把文档里的重要结构(标题、列表、表格、链接)作为 Markdown 保留下来。输出虽然也能看,但它的定位是给文本分析工具消费的,而不是给人做高保真排版。

它目前支持 PDF、PowerPoint、Word、Excel、图片(EXIF 元数据加 OCR)、音频(EXIF 元数据加语音转写)、HTML、CSV/JSON/XML 等文本格式、ZIP 压缩包(遍历其中内容)、YouTube 链接和 EPub 等。为什么用 Markdown?因为 Markdown 极接近纯文本、标记极少,却仍能表达文档结构;像 GPT-4o 这样的主流大模型原生就"会说"Markdown,而且 Markdown 习惯在 token 效率上很划算。
具体到每类文件,它抽取的重点各不相同:Word 和 PowerPoint 会保留标题层级、正文与项目符号列表;Excel 会把表格转成 Markdown 表格;PDF 抽取文本与版式,扫描件则要靠 OCR 插件或 Azure 云端能力;HTML 会去掉脚本样式、保留正文结构与链接;图片除了 EXIF 元数据,还能让 LLM 用一段话描述画面内容;音频会做语音转写;传入 YouTube 链接时直接抓该视频的字幕;ZIP 会解压并逐个处理里面的文件。这种"一个入口吃所有格式"的特性,正是它被大量 RAG 项目用作文档加载器的原因。
一、项目官方信息
| 项目 | 信息 |
|---|---|
| 项目名称 | MarkItDown |
| 项目定位 | 把 PDF / Office / 图片 / 音频 / 网页等文件转成 Markdown,供 LLM 管线使用 |
| 维护组织 | Microsoft |
| 代码仓库 | microsoft/markitdown |
| 主要语言 | Python |
| PyPI 包 | markitdown |
| 开源协议 | MIT |
| Star 数 | 约 192.6k |
| Python 版本 | 3.10 至 3.14 |
二、项目背景
把喂给大模型的文档统一成 Markdown,是 RAG 和文档智能管线里绕不开的一步。Word、PDF、PPT、Excel 各有各的二进制格式,表格和标题在不同软件里的语义也不一样;如果直接把原始字节丢给模型,模型既读不懂,也浪费 token。MarkItDown 解决的就是"入口格式归一"这个问题:你给它一个任意格式文件,它吐回一份保留了结构的 Markdown,让后续的切片、向量化、问答都能在同一套文本上进行。
它和同类工具的区别在于"为 LLM 优化":不追求排版还原,而追求把标题层级、表格、列表、链接这些对语义最重要的结构转成 Markdown 语法。图片还能借助 LLM Vision 生成描述,音频能转写,YouTube 链接能取字幕,ZIP 能批量遍历。这让它成为搭文档问答、知识库导入时非常顺手的前置工具。
实际工作里,一个知识库项目往往要面对几十种来源:销售发来的 Word 合同、会议留下的 PPT、财务导出的 Excel、扫描的 PDF、网页存档、甚至一段录好的会议音频。如果每种格式都写一套解析代码,不仅重复劳动,还容易在表格合并单元格、标题层级错乱上踩坑。MarkItDown 把这些杂活收进一个统一入口,你只需 md.convert("任意文件"),它内部按后缀或内容选择对应的转换器,吐回一份干净的 Markdown。这份 Markdown 再去做切片、embedding、入库,整个管线的入口就整齐了。
三、核心特性
- 多格式转换:PDF、Word、PowerPoint、Excel、HTML、CSV/JSON/XML、EPub、ZIP。
- 图片理解:提取 EXIF 元数据,并可选调用 LLM Vision 生成图片描述。
- 音频转写:提取音频元数据,支持 wav/mp3 语音转写。
- YouTube 字幕:直接传入 YouTube 链接抓取转写文本。
- 插件生态:支持第三方插件,插件默认关闭,可用
--use-plugins启用;GitHub 上搜#markitdown-plugin。 - markitdown-ocr 插件:给 PDF/DOCX/PPTX/XLSX 增加 OCR,用 LLM Vision 从内嵌图片里抽文字,无需新增 ML 库。
- Azure 集成:可选接 Azure Document Intelligence 或 Content Understanding,做云端版式分析、OCR、结构化字段抽取(YAML front matter)和音视频处理。
- 可选依赖分包:用
[all]一次装全,或按[pdf,docx,pptx]等子集按需安装。
转换器的设计是模块化的:每种格式对应一个 converter,主程序按文件类型路由。内置转换器完全离线运行,不花云端费用;当你遇到扫描版 PDF、复杂表格或需要抽出"发票金额、合同条款"这类字段时,再按需启用 Azure 的云端能力。这种"本地够用、云端增强"的分层,让你既能在普通文档上零成本跑批,又能在难啃的文件上调用更强的版式分析。插件机制则把扩展权交给社区——想支持新格式不必改主仓库,写一个带 #markitdown-plugin 标签的包即可独立发布。
四、环境要求
- Python 3.10 至 3.14:官方建议用虚拟环境避免依赖冲突。
- venv:
python -m venv .venv && source .venv/bin/activate。 - uv:
uv venv --python=3.12 .venv,之后用uv pip install装包。 - Anaconda:
conda create -n markitdown python=3.12再conda activate markitdown。 - 安全提醒:MarkItDown 以当前进程权限做 I/O,像
open()一样能访问进程能访问的资源;在不可信环境里要先清洗输入,优先调用最窄的转换函数(如convert_local()或convert_stream())。
五、部署步骤
方式一:pip 安装(推荐)
pip install 'markitdown[all]'
从源码安装:
git clone git@github.com:microsoft/markitdown.git
cd markitdown
pip install -e 'packages/markitdown[all]'
只想用部分格式可以按需装,例如 pip install 'markitdown[pdf, docx, pptx]' 只装 PDF、Word、PPT 的依赖。可用的可选依赖包括 [all]、[pptx]、[docx]、[xlsx]、[xls]、[pdf]、[outlook]、[az-doc-intel]、[az-content-understanding]、[audio-transcription]、[youtube-transcription]。
方式二:命令行直接转换
markitdown path-to-file.pdf > document.md
或用 -o 指定输出文件:
markitdown path-to-file.pdf -o document.md
也支持管道输入:
cat path-to-file.pdf | markitdown
方式三:Docker 浏览器/服务器端部署
docker build -t markitdown:latest .
docker run --rm -i markitdown:latest < ~/your-file.pdf > output.md
容器以标准输入接收文件、标准输出打印 Markdown,适合把它作为文档处理管线里的一个无状态环节串进网页服务或批量脚本。需要接 Azure 时,在运行时把 endpoint 与 key 通过环境变量传入即可。批量处理一个文件夹时,可以用 shell 循环对每个文件调一次 markitdown,把结果落到对应的 .md 文件,再喂给后续的切片与入库脚本。
六、使用方法
Python 基础用法:
from markitdown import MarkItDown
md = MarkItDown(enable_plugins=False)
result = md.convert("test.xlsx")
print(result.markdown)
用大模型描述图片(目前用于 pptx 和图片文件):
from markitdown import MarkItDown
from openai import OpenAI
client = OpenAI(max_retries=5)
md = MarkItDown(llm_client=client, llm_model="gpt-4o")
result = md.convert("example.jpg")
print(result.markdown)
启用插件做 OCR:
from markitdown import MarkItDown
from openai import OpenAI
md = MarkItDown(enable_plugins=True, llm_client=OpenAI(), llm_model="gpt-4o")
result = md.convert("document_with_images.pdf")
print(result.markdown)
接 Azure Document Intelligence 时,可在命令行指定模型、分析附加项和查询字段:
markitdown document.pdf --use-docintel \
--endpoint "<document_intelligence_endpoint>" \
--docintel-model-id prebuilt-layout \
--docintel-features "ocrHighResolution,styleFont" \
--docintel-query-fields "Title,Author"
可用的附加项有 barcodes、formulas、keyValuePairs、languages、ocrHighResolution、styleFont,其中 formulas、ocrHighResolution、styleFont 与 queryFields 会额外计费。命令行也支持管道,cat file.pdf | markitdown 适合在脚本里把它接成一环。
除了命令行和 Python API,它还提供 markitdown-mcp 包,能把文档转换能力作为 MCP 工具暴露给 Claude 这类 Agent,让 Agent 直接读 PDF 和图片。这在实际里很实用:你不必先手动转一份 Markdown 再贴给模型,Agent 自己就能调用转换工具拿到文本。
接 Azure Content Understanding 做结构化字段抽取时,设置 cu_endpoint,文档、视频、音频会自动路由到对应分析器;也可以用 cu_file_types 限定只让某类格式走云端,控制费用。安全方面,托管场景优先用 convert_local()(只读本地文件)或 convert_stream()(自己开流),而不是默认的 convert(),后者能处理远程 URI,权限最宽。
三种云端能力的分工值得记清楚:内置转换器是离线、按格式抽取,零成本但没有字段抽取;Azure Document Intelligence 提供云端版式分析和可选的 YAML front matter 字段,支持自定义模型 ID;Azure Content Understanding 更进一步,能处理音视频、用自定义分析器抽领域字段,并把字段序列化成 YAML front matter。视频目前只有 Content Understanding 能处理。每次走 CU 路由的 convert() 都是一次计费的 Azure API 调用,所以官方建议用 cu_file_types 把云端调用限制在真正需要的格式上。
在典型的知识库导入流程里,MarkItDown 往往是第一步:先把异构文档统一成 Markdown,再用切片器按标题或长度切分,接着向量化入库。它的价值在于把"读不懂的二进制"变成"模型能直接消费的纯文本",而且保留了结构信息,让切片不至于把一个表格拦腰截断。对个人用户,它可以把一堆旧 Word 笔记批量转成 Markdown 归档;对开发者,它是 RAG 加载器背后那把瑞士军刀;对企业,配合 Azure 的结构化字段能力,它能把发票、合同里的关键字段直接抽出来写进 front matter,省去再写一遍正则解析。
七、常见问题 FAQ
Q:输出能直接给人排版看吗? A:不追求高保真排版,它面向 LLM 消费,重点是保留标题、表格、列表等结构;给人精排请用专门的文档工具。
Q:图片里的文字能识别吗? A:装 markitdown-ocr 插件并传入 llm_client/llm_model,即可用 LLM Vision 从 PDF/DOCX 内嵌图片中抽文字;不传则 OCR 被静默跳过。
Q:一定要装全部可选依赖吗? A:不必。默认用 [all] 最省事,也可以 pip install 'markitdown[pdf,docx]' 按需装,减少体积。
Q:能处理远程文件或网页吗? A:convert() 能处理本地文件、远程 URI 和字节流,但在不可信环境里有安全风险,建议改用 convert_local() 或自己 requests.get() 后传 convert_response()。
Q:和 Azure Document Intelligence 是什么关系? A:那是可选的云端增强。内置转换器离线免费;Doc Intel 和 Content Understanding 提供更强的版式分析、OCR 和结构化字段抽取,但按 Azure API 调用计费。
Q:支持哪些 Python 版本? A:3.10 到 3.14,建议用虚拟环境隔离依赖。
Q:能把它做成网页服务吗? A:主仓库明确不收 Web 服务器、REST API 或前端界面,它定位是 Python 库。你可以自己用 FastAPI 包一层 HTTP 服务,或用 Docker 把它当命令行工具串进管线,但要在外面做好输入校验和路径限制。
Q:插件怎么写? A:参考仓库里的 packages/markitdown-sample-plugin,把新格式做成独立包,在 GitHub 上打 #markitdown-plugin 标签即可被他人搜到;安装后用 markitdown --list-plugins 查看、--use-plugins 启用。
总体而言,MarkItDown 适合作为文档智能管线的"第一道工序"。它不替代切片器、向量库或问答模型,而是把五花八门的输入格式统一成模型能读懂的 Markdown。内置能力离线、零成本、开箱即用;当遇到扫描件、复杂表格、音视频或需要抽字段时,再通过插件和 Azure 云端能力增强。对想快速搭知识库的人,pip install 'markitdown[all]' 加一行 md.convert() 就能跑通;对要上线的服务,重点则放在输入清洗和调用最窄的转换 API 上。
局限与注意
纯本地包对扫描件和复杂版式的 OCR 能力有限,这类文件要启用 Azure 插件;它输出的是可读 Markdown,不是为向量切片优化的,精细表格和图注可能需要后处理。遇到加密或损坏文件会报错,批量跑时建议捕获异常、跳过坏文件并记录清单。
在流水线里怎么接它
MarkItDown 最常见的位置是文档入库前的"归一化层":用户或爬虫扔进来什么格式都有,先过 MarkItDown 变成统一 Markdown,再交给切片、向量化、问答或摘要。命令行适合批量扫目录,Python 库适合嵌在服务里;对扫描件 PDF,用 azure 插件走 Azure Document Intelligence 能拿到 OCR 和版面,纯本地装默认包则没有这个能力。注意它输出的是"可读 Markdown",不是为机器切片优化的,表格和多级标题通常保留良好,复杂版式可能需要后处理。
一个最小可用流程
把一批合同、报表或论文放进目录,先 markitdown path -o out.md 跑通看效果,再在 Python 里按文件类型选择是否启用插件;对转换失败的文件单独记录,不要让它卡住整条管线。它的定位是轻量、免费、离线优先,重活交给上游 OCR 和下游向量化。
总体而言,MarkItDown 是文档智能管线里值得放进工具箱的"格式归一器":内置能力离线免费、开箱即用,扫描件和复杂表格再靠插件与 Azure 云端能力增强。它不替你做切片、向量化或问答,而是把五花八门的输入变成模型能读的 Markdown,让后续管线建立在整齐的文本之上。
- GitHub 仓库:microsoft/markitdown
- PyPI 包:markitdown
- 同类工具参考:deanmalmgren/textract
- Azure Content Understanding:官方文档
- Azure Document Intelligence:官方文档
- 问题反馈:GitHub Issues
小结:MarkItDown 把五花八门的文档归一成模型能读的 Markdown,本地免费离线、开箱即用;重活交给上游 OCR 和下游向量化,它自己只做干净利落的格式归一。
适用场景:把扫描合同、报表、论文统一转成 Markdown 喂给 RAG 或摘要;批量归档前先做格式归一。它不替你切片和向量化,而是让后续管线建立在整齐文本上。