【原创实践】Python 将 Markdown 文件转换为 Word(docx)完整实现

Python 将 Markdown 文件转换为 Word(docx)完整实现

在实际开发中,经常会遇到将 Markdown 文档转换为 Word(.docx)的需求,例如:

  • 技术文档从 Markdown 迁移到 Word

  • 自动生成可下载的 Word 报告

  • 与 Dify、FastAPI 等系统结合做文档导出

本文基于 python-docx + markdown + BeautifulSoup ,实现一个不依赖接口、直接读取 Markdown 文件并生成 Word 文件的完整方案,支持常见 Markdown 语法。


参考链接 https://mp.weixin.qq.com/s/vyz5d9Hya9UEEEvOiro9Vg

一、实现思路说明

整体转换流程如下:

  1. 使用 markdown 库将 Markdown 文本转换为 HTML

  2. 使用 BeautifulSoup 解析 HTML 结构

  3. 遍历 HTML 节点,映射为 Word 中的对应元素

  4. 使用 python-docx 生成并保存 .docx 文件

支持的 Markdown 元素包括:

  • 标题(h1--h6)

  • 段落

  • 无序 / 有序列表

  • 代码块

  • 行内代码、加粗、斜体

  • 表格


二、依赖安装

bash 复制代码
pip install python-docx markdown beautifulsoup4

三、完整代码实现

python 复制代码
from docx import Document
from docx.shared import Pt
from bs4 import BeautifulSoup
import markdown
import uuid
import os

FILE_DIR = "static"
os.makedirs(FILE_DIR, exist_ok=True)


def md_to_word(md_text: str) -> str:
    """
    将 Markdown 文本转换为 Word,返回生成的文件名
    """
    html = markdown.markdown(
        md_text,
        extensions=["extra", "tables", "fenced_code"]
    )

    soup = BeautifulSoup(html, "html.parser")
    doc = Document()

    for element in soup.contents:
        handle_element(doc, element)

    filename = f"{uuid.uuid4().hex}.docx"
    file_path = os.path.join(FILE_DIR, filename)
    doc.save(file_path)

    return filename


def handle_element(doc, el):
    if not hasattr(el, "name") or el.name is None:
        return

    # 标题
    if el.name in ["h1", "h2", "h3", "h4", "h5", "h6"]:
        doc.add_heading(el.get_text(), level=int(el.name[1]))
        return

    # 段落
    if el.name == "p":
        p = doc.add_paragraph()
        add_inline_text(p, el)
        return

    # 无序列表
    if el.name == "ul":
        for li in el.find_all("li", recursive=False):
            p = doc.add_paragraph(style="List Bullet")
            add_inline_text(p, li)
        return

    # 有序列表
    if el.name == "ol":
        for li in el.find_all("li", recursive=False):
            p = doc.add_paragraph(style="List Number")
            add_inline_text(p, li)
        return

    # 代码块
    if el.name == "pre":
        code_el = el.find("code")
        code = code_el.get_text() if code_el else el.get_text()
        p = doc.add_paragraph()
        run = p.add_run(code)
        run.font.name = "Courier New"
        run.font.size = Pt(10)
        return

    # 表格
    if el.name == "table":
        rows = el.find_all("tr")
        cols = rows[0].find_all(["th", "td"])
        table = doc.add_table(rows=len(rows), cols=len(cols))
        table.style = "Table Grid"

        for r, row in enumerate(rows):
            for c, cell in enumerate(row.find_all(["th", "td"])):
                paragraph = table.rows[r].cells[c].paragraphs[0]
                run = paragraph.add_run(cell.get_text())
                if cell.name == "th":
                    run.bold = True


def add_inline_text(paragraph, el):
    """
    处理行内样式:加粗、斜体、行内代码
    """
    for node in el.contents:
        if isinstance(node, str):
            paragraph.add_run(node)
        else:
            run = paragraph.add_run(node.get_text())
            if node.name == "strong":
                run.bold = True
            elif node.name == "em":
                run.italic = True
            elif node.name == "code":
                run.font.name = "Courier New"
                run.font.size = Pt(10)


def md_to_word_from_file(md_file_path: str) -> str:
    """
    从 Markdown 文件生成 Word
    """
    with open(md_file_path, "r", encoding="utf-8") as f:
        md_text = f.read()

    return md_to_word(md_text)


if __name__ == "__main__":
    md_path = "jd.md"   # Markdown 文件路径
    filename = md_to_word_from_file(md_path)
    print("生成的 Word 文件:", filename)

四、使用说明

  1. 将 Markdown 文件(如 jd.md)放到当前目录

  2. 运行脚本:

bash 复制代码
python md_to_word.py
  1. 程序会在 static/ 目录下生成一个 .docx 文件,文件名为 UUID

五、适用场景

  • FastAPI / Flask 文档导出

  • Dify 工作流中生成 Word 报告

  • Markdown 文档批量转 Word

  • 内部系统自动生成可编辑文档


六、可优化方向

  • 增加图片(img)支持

  • 支持代码高亮样式

  • 表格列宽自适应

  • 自定义标题样式、字体、行距

  • 与 FastAPI 接口结合返回下载地址


七、总结

本文实现了一个轻量、可控、易扩展的 Markdown 转 Word 方案 ,不依赖外部接口,适合后端服务或本地脚本使用。

对于需要文档导出、报告生成的场景,这种方式在稳定性和可维护性上都具有明显优势。

如果你后续需要 FastAPI 接口版Dify 工作流集成版样式增强版,可以在此基础上直接扩展。

相关推荐
爱吃山竹的大肚肚2 小时前
在Java中,从List A中找出List B没有的数据(即求差集)
开发语言·windows·python
企微自动化2 小时前
企业微信二次开发:深度解析外部群主动推送的实现路径
java·开发语言·企业微信
_修铁路的2 小时前
【Poi-tl】 Word模板填充导出
java·word·poi-tl
我的offer在哪里2 小时前
c++的回调函数
开发语言·c++
智航GIS2 小时前
ArcGIS大师之路500技---048计算流水号
python·arcgis
一棵开花的树,枝芽无限靠近你2 小时前
【face-api.js】2️⃣ NetInput - 神经网络输入封装类
开发语言·javascript·神经网络
yongche_shi2 小时前
第九十九篇:Python在其他领域的应用:游戏开发、物联网、AIoT简介
开发语言·python·物联网·游戏开发·aiot
froginwe112 小时前
Node.js 回调函数
开发语言
期待のcode2 小时前
Java中的继承
java·开发语言