用 markdown 库最稳妥,它基于状态机准确解析嵌套、转义和边缘 case;正则无法可靠处理 Markdown 复杂结构;需注意扩展启用、HTML 安全过滤及自定义渲染需写扩展类。

直接用 markdown 库最稳妥,别自己手写解析器——99% 的需求它都覆盖了,且能正确处理嵌套、转义和边缘 case。
为什么不用正则硬匹配标题/列表?
Markdown 的嵌套规则(比如列表里套引用块、代码块里含反引号)会让正则迅速失控。你写的 re.sub(r'##\s+(.+)', r' 看似简单,但遇到下面这些就会崩:\1
', text)
- 行内代码里的
## hello被误转 - 引用块中
> ## 标题本该保留原样,却被替换了 - 无序列表项里带换行的描述,正则无法跨行匹配
标准库不提供 Markdown 解析,markdown 包是事实上的参考实现,基于状态机,能准确识别块级/行内结构。
安装与基础用法:三行搞定转换
运行 pip install markdown 后,核心就是调用 markdown.markdown():
import markdown
html = markdown.markdown("# Hello\n\n- item 1\n- item 2")
print(html)
# 输出: <h1>Hello</h1>\n
- \n
- item 1 \n
- item 2 \n
注意两点:
-
markdown.markdown()默认不启用表格、脚注等扩展,纯 CommonMark 子集 - 输入文本必须是字符串,不能是文件对象或字节;若读自文件,请先用
open(...).read()并确保编码为 UTF-8 - 输出不含
或外壳,只是片段 HTML,需自行包裹
常用扩展怎么开?比如表格和代码高亮
表格支持靠 tables 扩展,代码块高亮需要配合 pygments 和 fenced_code:
python\nprint("hello")\n
关键细节:
-
tables和fenced_code是内置扩展名字符串,直接传;而CodeHiliteExtension是类,要实例化 - 高亮依赖系统已安装
pygments(pip install pygments),否则代码块会退化为普通<code></code>
- 扩展顺序无关,但
fenced_code必须开启才能识别```语法
安全问题:用户输入必须清理
markdown.markdown() 默认允许原始 HTML,如果输入来自用户(比如评论框),<script>alert(1)</script> 会被原样输出——XSS 风险。
解决方法只有两个:
- 加
safe_mode='escape'参数(旧版)或改用mdx_htmlsanitizer扩展(推荐) - 更可靠的是在转换后用
bleach.clean()二次过滤:bleach.clean(html, tags=['p', 'h1', 'h2', 'ul', 'li'], strip=True)
别信“我只允许特定标签”这种手动白名单逻辑,HTML 解析器比人眼靠谱得多。
真正麻烦的是自定义渲染逻辑(比如把图片 URL 自动转成懒加载格式),那得写扩展类,不是改几行就能搞定的事。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











