PDF转Markdown保留格式:不丢结构的转换方法

作者 pdftomd.tools 团队 · 更新于 · 阅读约 7 分钟

简短回答:PDF转Markdown保留格式,只能保留 Markdown 本身能表达的结构:标题、列表、表格和代码。先确认文件有真正的文字层,再用 免费的PDF转Markdown工具 转换,使用结果之前检查一遍标题、列表和表格。字体、颜色、精确间距这类视觉样式,永远不会跟过来。

插图:一页带标题、段落和表格的 PDF,变成结构相同的 Markdown 文件

哪些“格式”能在 Markdown 里保留(哪些不能)

PDF 描述的是页面长什么样。这个格式由 ISO 32000-2 定义,它在页面的各个位置存放字形,外加字体、线条和图片。除非作者加了标签,它自己并不知道“这是一个标题”,而现实中的大多数文件都没有可用的标签。Markdown 正好相反:它记录每个块是什么(标题、列表项、表格行),外观交给显示它的软件。

所以,有人问怎样把 PDF 转成 Markdown 又不丢格式时,老实的回答是:“格式”分成两类。结构可以重建;外观不行,因为 Markdown 没有表达外观的语法。

转换能带过去的内容
PDF 里的格式在 Markdown 中说明
标题(字号更大)能根据字号重建,需检查层级
项目符号和编号列表能编号是重新写的,不是照抄
表格能,转成竖线表格一行表头,不支持合并单元格
链接只有印在页面上的网址藏在文字后面的链接读不到
等宽字体的代码能,转成代码块不知道是哪种语言
粗体和斜体我们的工具不能需要分析字重
图片和图表不能需单独导出
字体、颜色、页面版式不能Markdown 没有对应语法
“Markdown 格式语法最重要的设计目标,是让它尽可能易读。”
John Gruber, Markdown 项目主页,Daring Fireball(译文)

正是这个设计目标,让这笔交换划算。你放弃了页面的精确外观,换来易读的纯文本:Git diff 干净,可以直接粘贴到 wiki 或聊天模型里。CommonMark 规范 定义了核心语法,GitHub Flavored Markdown 又加上了表格和任务列表。

先检查 PDF:文字层、分栏、字体

想让 PDF转Markdown保留格式,要从转换之前开始:花两分钟检查,能省下一小时修补。随便用一个阅读器打开文件,测一下文字层:试着选中一句话,粘贴到别处。能粘贴,说明页面上有真正的文字。如果整页被当成一整块选中,或者什么都选不中,那就是扫描版 PDF,也就是一张没有可读字符的页面照片。

插图:放大镜照出双栏页面上可选中的文字行,旁边是一张带警告标志的扫描页
能选中文字,转换器就有东西可读;扫描件没有。

命令行里,Poppler 的 pdffonts 会列出文件用到的字体。页面上满是文字,列表却是空的,基本可以断定是扫描件。接着留意三个版式特征,它们决定输出有多干净:

  • 分栏。双栏的论文和简报,会迫使转换器去猜阅读顺序。
  • 标题样式。用大字号排的标题很容易识别;只是加粗、字号和正文一样的标题,在按字号识别的方式下看起来就是普通段落。
  • 字体。等宽字体的代码可以转成代码块。少见的字体编码可能让文字变成方框或乱码,这是任何转换器都修不好的。
截图:放入纯图片 PDF 后,我们的转换器显示“没有可读取的文字”,并说明不做 OCR
我们的转换器处理纯图片文件时的截图:提示文件看起来是扫描件,并说明只读取文字层、不做 OCR。

分步操作:PDF转Markdown保留格式

这套流程适用于任何读取文字层的转换器。我们用自己的工具,因为能说清它到底做了什么:用 pdf.js 读取文字层,把单词拼成行,再根据大小和位置重建标题、列表、表格和代码。文件不会上传。

  1. 打开转换器,放入文件。除非你需要原始文字,否则保持“清理 AI 残留”开启。
  2. 看预览下方的摘要。它会显示页数、字符数和找到了几张表。如果很多页只有极少的字符,说明其中有些页是扫描件。
  3. 从上到下浏览预览。先看标题层级,再看列表,最后看表格。
  4. 复制或下载 .md 文件,在编辑器里打开,旁边开着预览。
  5. 按下面的清单修正问题,然后提交或粘贴结果。
截图:在我们的转换器里完成 PDF转Markdown保留格式,预览中有标题、列表和表格
截图:一页带标题、列表和表格的测试文件,转成 Markdown 后格式完整,摘要显示找到 1 张表。

如果你主要转报告和手册,PDF转MD工具 页面对标题和列表规则讲得更细。以表格为主的文件,请看我们的 PDF 表格转 Markdown 指南。

标题、列表和表格:要检查什么

标题、列表和表格撑起了文档的大部分结构,所以读者在意的格式能不能保住,主要看这三样。

标题

为了在转换中保住标题,转换器会把每一行的高度和正文比较。我们的工具把最大的几档字号对应到 # 到 ####,还会把较短的全大写行当作标题。检查两件事:文档标题是不是唯一的 #;章节和小节的层级有没有对调。比正文只大一点点的章标题,可能会降一级。

列表

列表项根据项目符号(•、–、*)或带句点、括号的数字识别。编号项每次都写成 1.,Markdown 会显示成 1、2、3。注意换到第二行的列表项:在 PDF 里第二行只是另一段文字,但它应该留在同一个列表项里。

表格

表格最常需要手动处理。有框线的表格和对齐整齐的列,通常转得不错。我们用 12 种表格版式测试,8 种单表版式和一页两张表的版式都还原出了预期的行,双栏文字页也正确地没有生成表格。旋转 90 度的表格没有被识别。合并单元格会被拆开,因为竖线表格表达不了合并。

会丢失的:粗体/斜体、插图、分栏

没有哪个工具能把 PDF 转成 Markdown 而完全不丢格式。有些损失来自格式本身,有些是具体工具的限制,分清楚很有用。

  • 粗体和斜体。Markdown 有 **粗体** 和 *斜体*,所以这是工具的限制,不是格式的限制。我们的转换器还识别不了强调,只输出不带标记的文字。在有含义的地方(比如警告)把强调补回去。
  • 插图和图表。它们是绘图或嵌入的图片,不是文字,会被跳过。需要的图片单独导出,再用 ![alt](file.png) 链接。
  • 脚注。脚注文字会留下,但脚注标记和脚注之间的对应关系没了。重要的脚注手动补上。
  • 多栏版式。阅读顺序不明确时,栏与栏可能混在一起。检查每一节的第一页。
  • 精确间距和分页。页面边界会被去掉,被分页切断的段落在安全的情况下会重新接上。

重复的页眉页脚和页码是个特例:这种格式通常你巴不得去掉。我们的转换器会删除在大多数页面顶部或底部重复出现的行,所以“年度报告 · 第 7 页”不会插在段落中间。

转换后的整理清单

插图:一份勾了三项的清单,旁边编辑器里一支铅笔正在改一行

PDF转Markdown保留格式的最后一步,是快速过一遍。在编辑器里开着预览,对照这份清单;一份普通报告几分钟就能检查完。

  • 顶部一个 # 标题,章节用 ##。跳级的地方改过来。
  • 没有把零散的页眉或图片说明当成标题。
  • 列表项完整,换行的部分留在所属的列表项里。
  • 每张表都有表头,每一行的单元格数量相同。
  • 合并或空白的单元格已经填好,或在表格下方加注说明。
  • 会改变意思的地方补上了强调。
  • 原来有插图的位置加了图片占位或链接。
  • 补上链接:我们的转换器会把印出来的网址当文字保留,但读不到藏在文字后面的链接。

对聊天模型或 RAG 索引来说,标题最重要,因为它们会成为分块的边界;我们的 大模型指南 专门讲了这种场景。

什么时候换别的工具更合适(OCR、版面模型)

读取文字层的转换器,适合从文字处理软件、演示软件或排版系统导出的文件。下面三种情况,与其和输出较劲,不如换工具。

  • 扫描件。扫描版 PDF 要先做 OCR。OCRmyPDF 能给扫描文件加上可搜索的文字层,之后文字转换器就能读了。
  • 复杂版式。对于公式多、多栏、表格密集的论文,Docling 这类基于版面模型的工具声明支持页面版式、阅读顺序和表格结构。它们用 Python 在本地运行,安装更麻烦一些。
  • 大量扫描件和文字混合的文件。marker 可以把文字层、OCR 和可选的 LLM 辅助结合起来。商用前先看清模型权重的许可条款。

不管选哪个,检查这一步都要保留:文件里从没存过的格式,任何工具都保不住。我们的 关于 页面列出了我们的转换器做不到的事,包括 OCR。

参考来源

  1. ISO 32000-2:2020 Document management — Portable document format — Part 2: PDF 2.0 — ISO, 2020
  2. CommonMark Spec, version 0.31.2 — CommonMark, 2024
  3. GitHub Flavored Markdown Spec — GitHub, 2019
  4. Markdown — Daring Fireball (John Gruber), 2004
  5. pdf.js — Mozilla
  6. pdffonts(1) manual page — Poppler / Debian
  7. OCRmyPDF — OCRmyPDF project
  8. Docling — Docling project

常见问题

PDF转Markdown能保留格式吗?

结构可以保留:标题、列表、表格、代码,以及页面上印出来的网址。字体、颜色、分栏和精确间距这类视觉样式保不住,因为 Markdown 没有对应语法。Markdown 支持粗体和斜体,但我们的转换器暂时识别不了。

为什么我的标题变成了普通段落?

包括我们在内,大多数转换器靠字号识别标题。加粗但字号和正文一样的标题,看起来就像段落。手动加上 #,或者看看原文档能不能用真正的标题样式重新导出。

怎么知道我的 PDF 有没有文字层?

试着选中并复制一句话。能以文字形式粘贴,就有文字层。命令行里,pdffonts file.pdf 会列出文件用的字体;页面满是文字却一个字体都没有,通常就是扫描件。

转换时表格会怎样?

识别出的表格会变成带一行表头的 GitHub 风格竖线表格。合并单元格会拆开,内容放在第一格,后面跟空格子;跨页的表格会变成每页一张表。解决办法见我们的 表格指南。

扫描版 PDF 能转换吗?

读取文字层的转换器不行。扫描件没有可读字符,所以我们的工具会显示“没有可读取的文字”。先用 OCRmyPDF 之类的工具做 OCR,再转换结果。OCR 本身会带来错误,所以扫描件更难保留格式。

转换时文件会上传吗?

我们的转换器不会。PDF 由浏览器标签页里的 pdf.js 读取。网站收集哪些信息,见我们的 隐私政策。