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

【原创实践】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)
  • 段落
  • 无序 / 有序列表
  • 代码块
  • 行内代码、加粗、斜体
  • 表格

二、依赖安装

pip install python-docx markdown beautifulsoup4 

三、完整代码实现

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)defmd_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 defhandle_element(doc, el):ifnothasattr(el,"name")or el.name isNone: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 inenumerate(rows):for c, cell inenumerate(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 =Truedefadd_inline_text(paragraph, el):""" 处理行内样式:加粗、斜体、行内代码 """for node in el.contents:ifisinstance(node,str): paragraph.add_run(node)else: run = paragraph.add_run(node.get_text())if node.name =="strong": run.bold =Trueelif node.name =="em": run.italic =Trueelif node.name =="code": run.font.name ="Courier New" run.font.size = Pt(10)defmd_to_word_from_file(md_file_path:str)->str:""" 从 Markdown 文件生成 Word """withopen(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. 运行脚本:
python md_to_word.py 
  1. 程序会在 static/ 目录下生成一个 .docx 文件,文件名为 UUID

五、适用场景

  • FastAPI / Flask 文档导出
  • Dify 工作流中生成 Word 报告
  • Markdown 文档批量转 Word
  • 内部系统自动生成可编辑文档

六、可优化方向

  • 增加图片(img)支持
  • 支持代码高亮样式
  • 表格列宽自适应
  • 自定义标题样式、字体、行距
  • 与 FastAPI 接口结合返回下载地址

七、总结

本文实现了一个轻量、可控、易扩展的 Markdown 转 Word 方案,不依赖外部接口,适合后端服务或本地脚本使用。
对于需要文档导出、报告生成的场景,这种方式在稳定性和可维护性上都具有明显优势。

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

Read more

《二分查找:从 “折半” 到 “精准命中” 的算法逻辑拆解》

《二分查找:从 “折半” 到 “精准命中” 的算法逻辑拆解》

前引:算法面试中,二分查找是 “高频考点” 之一,它不仅能考察求职者的逻辑思维,还能检验对时间复杂度优化的理解。而在实际开发中,二分查找更是处理 “有序数据查找” 问题的最优解无论是缓存查找、数据索引,还是参数优化,都能看到它的身影。但很多开发者对二分查找的理解停留在 “基础用法”,忽略了其在复杂场景下的拓展应用,也未能规避常见的边界错误。本文将结合面试真题和实战案例,全面解析二分查找的原理、优化技巧、场景延伸,帮你既能轻松应对面试,又能在实际开发中高效运用,真正发挥二分查找的 “效率优势”! 目录 【一】“二分”算法原理剖析 【二】简单的二分查找 (1)题目链接 (2)算法解析 【三】找目标范围 (1)题目链接 (2)算法解析 (3)代码 【四】搜索插入位置 (1)题目链接 (2)算法解析

By Ne0inhk
Flutter 三方库 linalg 的鸿蒙化适配指南 - 掌控高性能线性代数、矩阵运算实战、鸿蒙级算法中枢

Flutter 三方库 linalg 的鸿蒙化适配指南 - 掌控高性能线性代数、矩阵运算实战、鸿蒙级算法中枢

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 linalg 的鸿蒙化适配指南 - 掌控高性能线性代数、矩阵运算实战、鸿蒙级算法中枢 在鸿蒙跨平台应用处理 3D 图形变换、复杂的信号处理(DSP)或是端侧的小型机器学习模型时,高效的矩阵(Matrix)与向量(Vector)运算是一切算法的基石。如果你不想手写枯燥且易错的嵌套循环。今天我们要深度解析的 linalg——一个纯 Dart 实现的、遵循线性代数标准的专业级数学库,正是帮你搭建“算法堡垒”的数字基石。 前言 linalg 提供了一套直观且功能完备的线性代数 API。它不仅支持基础的向量加减、点积(Dot Product)和叉积(Cross Product),还涵盖了复杂的矩阵乘法、转置(Transpose)以及行列式计算。在鸿蒙端项目中,

By Ne0inhk
从冒泡到模拟q sort函数——初见排序算法的探索和思考

从冒泡到模拟q sort函数——初见排序算法的探索和思考

国庆中秋喜相连,万家团圆乐同庆。 各位小伙伴们大家好,我是此方,在此,先祝大家双节快乐! 我们都知道排序有很多种:例如冒泡排序,插入排序,快速排序,等等很多种。 而冒泡排序,是各种计算机语言中最经典的一种排序算法。 今天我将从冒泡排序开始,到实现qsort函数的模拟。逐层深入,探索排序问题。 并给出鄙人的一些拙见。 上正文: 一,冒泡排序:最经典的排序算法 假如有一个十元素整型数组,他是完全倒着排序的:就像这样 now,我们要按照从小到大的顺序将这十个数字重新排列。 如果我们想要用冒泡排序:那么他的逻辑应该是这样的: 首先让最左边的数字和他右边的数字比较:9>8,将9和8互换位置: 让9继续和他右边的数字比较,再互换位 以此类推:9不断的比较——>移动——>再比较:最后;会到达最右边,这样,我们就让最大的数字9放在了最低位置 然后是8,接下来是7,6,5.

By Ne0inhk

leetcode 链表 两数相加 rust解法分析

原题 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。 迭代解法 代码 impl Solution { pub fn add_two_numbers( l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>, ) -> Option<Box<

By Ne0inhk