DevTool 团队

网页正文提取为 Markdown:HTML 转换的场景与规则

为什么要手动把网页内容变成 Markdown?这篇讲清 HTML 转 Markdown 的三类真实场景(笔记归档、博客迁移、喂给大语言模型的干净素材),以及转换器的核心规则:标题与强调怎么映射、嵌套列表的缩进与有序起始号、GFM 表格的对齐、代码块的语言提取与围栏升级、语法字符为什么要按位置转义。附在线工具与 Markdown 生态的搭配用法。

为什么要把网页内容变成 Markdown

三个场景撑起了 HTML 转 Markdown 的真实需求:

  1. 笔记归档:读到好文章想存进 Obsidian/Notion——这些工具的「粘贴网页」常丢格式或带进广告杂质,复制 HTML 源码再转 Markdown 是最干净的路径
  2. 博客迁移:老站是 HTML 输出(WordPress 主题、手写页面),迁到 Hugo/Hexo/Astro 这类 Markdown 驱动的静态博客,逐篇转格式是必经之路
  3. 大语言模型的素材整理:把网页喂给模型做摘要/翻译/改写时,去掉导航栏脚注残渣的纯 Markdown 上下文最省 token、噪音最低

三个场景的共同点:要结构与正文,不要样式与杂质——这正是转换规则设计的出发点。

核心规则一:结构与强调的映射

直译的部分没有争议:h1-h6 映射 #-######,strong 映射 **,em 映射 *,行内 code 用反引号。有意思的是边界:

  • 包装标签透传:div/section/span 这类纯容器在 Markdown 里没有对应物,只保留内部内容
  • script/iframe/表单丢弃:交互元素在 Markdown 里无处安放,安全上也不该保留
  • 内联样式全丢:Markdown 哲学是内容与表现分离,颜色字号这类信息注定丢失

核心规则二:列表的深度还原

列表是最容易转坏的结构。要点有三个:

  • 嵌套缩进:子列表按两空格缩进逐层展开,乱一层整棵树就散架
  • 有序起始号:<ol start="5"> 要输出 5. 开头——编号是内容语义,丢了就错
  • 任务列表:列表项首位是 checkbox 时转 - [x]/- [ ](GFM 扩展),藏在段落里的 checkbox 则按表单元素丢弃

核心规则三:表格与代码块

表格走 GFM 扩展:表头行 + 对齐分隔行 + 数据行,对齐从 HTML 的 align 属性映射(:---/:---:/---:)。要诚实的是:现代网页的对齐多写在 CSS class 里,能映射到的对齐是少数——「表格结构保留」是确定的,「视觉对齐保留」不承诺。

代码块有两条:从 language-xxx class 提取语言标注围栏(```python);围栏升级——内容本身含三反引号时(比如这篇网页就是在讲 Markdown 语法),外层围栏自动升到四反引号,否则代码块在半途被截断。

核心规则四:转义——保住「渲染结果与原文一致」

这是最容易被轻视、却决定输出质量的一环。文本里恰好出现 *、_、[、行首 # 或 - 时,不转义就会意外变成强调/链接/标题/列表。规则按位置判断:

场景 处理
文本中的 * [ 前加反斜杠
snake_case 词中间的 _ 保留(前后是字母数字时不是强调语法)
行首的 # - 1. 转义,防止变标题/列表
表格单元格内的 | 转义,防止拆列
pre/code 内容 一律不转义(它就该是字面量)

工具与生态的搭配

HTML 转 Markdown 转换器把上述规则做全:粘贴源码实时转换,列表符号/强调风格/保留图片/GFM 表格四个开关适配目标编辑器惯例。转换结果想预览渲染效果,用 Markdown 在线预览反方向核对;README 类文档的预览工作流见这篇指南。编程化批量场景再用 markdownify/turndown 这类库——一次性任务,粘贴即得的在线工具成本最低。

常见问题

HTML 转 Markdown 的过程中会丢失什么?

四类:内联样式与 class/id(Markdown 没有对应语法);合并单元格与单元格内嵌套结构(GFM 表格不支持);script/iframe/表单控件等交互元素(安全与语法双重不支持);CSS 驱动的视觉信息(对齐多写在 class 里,只有 HTML align 属性的对齐能映射)。结构与文字内容是保住的——这正是「素材整理」场景需要的。

转 Markdown 时下划线和星号为什么要转义?

Markdown 把 * 与 _ 当强调语法、把 [ ] 当链接语法、行首的 # 与 - 当标题与列表——文本里恰好出现这些字符时会意外改变渲染结果(snake_case 变斜体、行首数字加点变列表)。转换器按位置转义:词中间的下划线保留、行首语法字符加反斜杠、表格单元格里的竖线转义——保住「渲染结果与原文一致」这个第一原则。

代码块里的三个反引号怎么处理?

围栏升级:内容本身包含 ``` 时,外层围栏自动升到四反引号或更长,直到不再与内容冲突——这也是 CommonMark 的标准做法。行内代码同理,内容含反引号时用双反引号包裹。转换 Markdown 教程类网页(代码块里就是反引号语法)时这条规则是刚需。

有哪些编程库可以做同样的转换?

Python 生态的 markdownify 与 html2text(命令行可独立用)、BeautifulSoup4 自写遍历;JavaScript/Node 的 turndown(浏览器与 Node 双端)与 unified 生态的 rehype-remark 管线;各静态博客框架(Hugo/Hexo)的导入器内部也是这类库。在线工具的优势是零环境成本:粘贴即得,适合一次性或低频任务。