python将Markdown文件格式转为Word文档的示例代码

Written by

in

文章目录
  • 要实现 Markdown 文件 → Word(.docx) 文件 的格式转换,核心思路是: 先用 python-markdown 库把 Markdown 文本/文件解析成 HTML 格式; 再用 python-docx 库将解析后的 HTML 内容,逐节点渲染到 Word 文档中,完成最终转换。
  • 该方案依赖 3 个核心库,直接在终端执行以下命令安装所有依赖: pip install python-markdown python-docx beautifulsoup4 python-markdown:核心 Markdown 解析库,负责 MD → HTML; python-docx:核心 Word 操作库,负责生成/编辑 .docx 文档; beautifulsoup4:辅助解析 HTML 节点,方便精准提取内容渲染到 Word。
  • 坑1:中文乱码/字体异常 解决方案:为所有文字节点指定中文字体(宋体/黑体),通过 qn('w:eastAsia') 强制生效; 核心代码:run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')。 坑2:Markdown 语法解析不全 解决方案:启用 python-markdown 的扩展库(extra/codehilite),支持表格、代码块、脚注等扩展语法。 坑3:列表嵌套/格式错乱 解决方案:用 recursive=False 限制列表子节点解析层级,配合 Word 内置的 List Bullet/List Number 样式,保证列表格式统一。 坑4:图片加载失败 解决方案:增加图片路径校验,若路径不存在则在 Word 中提示错误信息,避免程序崩溃。
  • 如果需要极简、无代码的转换方案,推荐使用成熟工具 pandoc,比手动开发的脚本支持的语法更全、兼容性更强:
  • 手动开发方案(python-markdown + python-docx):适合需要自定义转换规则(如字体、样式、格式)的场景,代码可灵活扩展; 工具方案(pandoc):适合快速批量转换,无需开发,开箱即用,兼容性最优; 核心避坑:处理中文时必须指定中文字体 + UTF-8 编码,解析列表时限制递归层级。 两种方案均可满足 Markdown → Word 的转换需求,可根据实际场景选择。 到此这篇关于python将Markdown文件格式转为Word文档的示例代码的文章就介绍到这了,更多相关python Markdown转Word内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python将Markdown文件转换为Word(docx)完整教学 Python轻松实现Word到Markdown的转换 Python实现将Markdown转为Word、HTML、PDF、PNG和JPG 基于Python实现Markdown与Word高保真互转 使用Python实现Markdown转Word工具 使用Python将Markdown文件转换为Word的三种方法 Python实现快速提取Word表格并转Markdown Python使用pypandoc将markdown文件和LaTex公式转为word 使用Python构建Markdown转Word文档转换器
  • 目录
    • 一、核心方案说明
    • 二、完整环境安装(一键执行)
    • 三、完整可运行代码(直接复用)
      • 版本1:基础版(支持绝大多数 MD 语法,满足日常需求)
      • 版本2:增强版(额外支持 表格、代码块、图片 语法)
    • 四、使用方法(3步极简操作)
      • 步骤1:准备源文件
      • 步骤2:修改文件路径
      • 步骤3:运行代码
    • 五、关键优化点(解决常见坑)
      • 六、支持的 Markdown 语法清单
        • 基础语法(基础版+增强版均支持)
        • 扩展语法(仅增强版支持)
      • 七、备选方案(更轻量化,一行命令转换)
        • 1. 安装 pandoc
        • 2. 一行命令转换
      • 总结

        要实现 Markdown 文件 → Word(.docx) 文件 的格式转换,核心思路是:

        • 先用 python-markdown 库把 Markdown 文本/文件解析成 HTML 格式
        • 再用 python-docx 库将解析后的 HTML 内容,逐节点渲染到 Word 文档中,完成最终转换。

        该方案依赖 3 个核心库,直接在终端执行以下命令安装所有依赖:

        pip install python-markdown python-docx beautifulsoup4
        
        • python-markdown:核心 Markdown 解析库,负责 MD → HTML;
        • python-docx:核心 Word 操作库,负责生成/编辑 .docx 文档;
        • beautifulsoup4:辅助解析 HTML 节点,方便精准提取内容渲染到 Word。

        支持标题(1-6级)、段落、加粗、斜体、有序列表、无序列表、超链接、图片、换行等核心语法,代码可直接复制运行:

        import markdown
        from docx import Document
        from docx.shared import Pt, Inches
        from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_PARAGRAPH_ALIGNMENT
        from docx.oxml.ns import qn
        from bs4 import BeautifulSoup
        import os
        
        def markdown_to_word(md_file_path, docx_file_path=None):
            """
            Markdown文件转Word文档核心函数
            :param md_file_path: 源Markdown文件路径(必填,如:./test.md)
            :param docx_file_path: 输出Word文件路径(可选,默认同目录同名.docx)
            """
            # 1. 校验源文件是否存在
            if not os.path.exists(md_file_path):
                print(f"错误:源文件 {md_file_path} 不存在!")
                return
            
            # 2. 默认输出路径(同目录、同名,后缀替换为.docx)
            if docx_file_path is None:
                docx_file_path = os.path.splitext(md_file_path)[0] + ".docx"
            
            # 3. 读取Markdown文件内容(指定UTF-8编码,避免中文乱码)
            with open(md_file_path, "r", encoding="utf-8") as f:
                md_content = f.read()
            
            # 4. Markdown → HTML(启用扩展,支持更完整语法)
            html_content = markdown.markdown(
                md_content,
                extensions=[
                    'extra',        # 支持表格、代码块、脚注等扩展语法
                    'sane_lists',   # 优化列表解析规则
                    'nl2br'         # 换行符n转为HTML的<br>标签
                ],
                extension_configs={}
            )
            
            # 5. 初始化Word文档对象
            doc = Document()
            
            # 6. 全局样式配置(统一字体、避免中文宋体异常)
            doc.styles['Normal'].font.name = '宋体'
            doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
            doc.styles['Normal'].font.size = Pt(12)  # 正文字号12号
            
            # 7. 解析HTML并渲染到Word
            soup = BeautifulSoup(html_content, "html.parser")
            parse_html_node(soup, doc)
            
            # 8. 保存Word文档
            doc.save(docx_file_path)
            print(f"转换成功!Word文件已保存至:{docx_file_path}")
        
        def parse_html_node(node, doc):
            """递归解析HTML节点,映射为Word对应样式"""
            # 处理标题(h1-h6)
            if node.name in [f'h{i}' for i in range(1,7)]:
                level = int(node.name[1])
                p = doc.add_paragraph()
                run = p.add_run(node.get_text(strip=True))
                # 标题样式:字号随级别递减,加粗
                run.font.size = Pt(20 - level * 2)
                run.font.bold = True
                run.font.name = '黑体'
                run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
                p.alignment = WD_ALIGN_PARAGRAPH.LEFT
            
            # 处理段落
            elif node.name == 'p':
                p = doc.add_paragraph()
                parse_inline_content(node, p)
            
            # 处理无序列表
            elif node.name == 'ul':
                for li in node.find_all('li', recursive=False):
                    p = doc.add_paragraph(style='List Bullet')
                    parse_inline_content(li, p)
            
            # 处理有序列表
            elif node.name == 'ol':
                for li in node.find_all('li', recursive=False):
                    p = doc.add_paragraph(style='List Number')
                    parse_inline_content(li, p)
            
            # 处理换行
            elif node.name == 'br':
                doc.add_paragraph()
            
            # 递归处理子节点(兼容嵌套结构)
            for child in node.children:
                if child.name:
                    parse_html_node(child, doc)
        
        def parse_inline_content(node, paragraph):
            """解析行内元素(加粗、斜体、超链接等),添加到指定段落"""
            for content in node.contents:
                if isinstance(content, str):
                    # 纯文本内容
                    run = paragraph.add_run(content)
                    run.font.name = '宋体'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
                    run.font.size = Pt(12)
                elif content.name == 'strong':
                    # 加粗文本(MD:**内容**)
                    run = paragraph.add_run(content.get_text())
                    run.font.bold = True
                    run.font.name = '宋体'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
                elif content.name == 'em':
                    # 斜体文本(MD:*内容*)
                    run = paragraph.add_run(content.get_text())
                    run.font.italic = True
                    run.font.name = '宋体'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
                elif content.name == 'a':
                    # 超链接(MD:[文本](链接))
                    text = content.get_text()
                    link = content.get('href', '')
                    run = paragraph.add_run(f"{text}({link})")
                    run.font.color.rgb = None  # 可自定义链接颜色
                    run.font.name = '宋体'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
        
        # ------------------- 调用示例 -------------------
        if __name__ == "__main__":
            # 替换为你的Markdown文件路径(相对路径/绝对路径均可)
            INPUT_MD_FILE = "./test.md"
            # 可选:指定输出Word路径,如 "./转换结果.docx"
            OUTPUT_DOCX_FILE = None
            
            markdown_to_word(INPUT_MD_FILE, OUTPUT_DOCX_FILE)
        

        日常使用中表格、代码块、图片是高频 MD 语法,在基础版上扩展该能力,满足更复杂的转换需求:

        import markdown
        from docx import Document
        from docx.shared import Pt, Inches, RGBColor
        from docx.enum.text import WD_ALIGN_PARAGRAPH
        from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
        from docx.oxml.ns import qn
        from bs4 import BeautifulSoup
        import os
        
        def markdown_to_word(md_file_path, docx_file_path=None):
            if not os.path.exists(md_file_path):
                print(f"错误:源文件 {md_file_path} 不存在!")
                return
            if docx_file_path is None:
                docx_file_path = os.path.splitext(md_file_path)[0] + ".docx"
        
            with open(md_file_path, "r", encoding="utf-8") as f:
                md_content = f.read()
        
            # 启用表格、代码块扩展
            html_content = markdown.markdown(
                md_content,
                extensions=['extra', 'sane_lists', 'nl2br', 'codehilite'],
                extension_configs={}
            )
        
            doc = Document()
            doc.styles['Normal'].font.name = '宋体'
            doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
            doc.styles['Normal'].font.size = Pt(12)
        
            soup = BeautifulSoup(html_content, "html.parser")
            parse_html_node(soup, doc)
            doc.save(docx_file_path)
            print(f"转换成功!Word文件已保存至:{docx_file_path}")
        
        def parse_html_node(node, doc):
            # 基础节点(标题、段落、列表)- 同基础版,此处省略,完整代码包含
            if node.name in [f'h{i}' for i in range(1,7)]:
                level = int(node.name[1])
                p = doc.add_paragraph()
                run = p.add_run(node.get_text(strip=True))
                run.font.size = Pt(20 - level * 2)
                run.font.bold = True
                run.font.name = '黑体'
                run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
            elif node.name == 'p':
                p = doc.add_paragraph()
                parse_inline_content(node, p)
            elif node.name == 'ul':
                for li in node.find_all('li', recursive=False):
                    p = doc.add_paragraph(style='List Bullet')
                    parse_inline_content(li, p)
            elif node.name == 'ol':
                for li in node.find_all('li', recursive=False):
                    p = doc.add_paragraph(style='List Number')
                    parse_inline_content(li, p)
            
            # 新增:处理表格
            elif node.name == 'table':
                rows = node.find_all('tr')
                row_count = len(rows)
                col_count = len(rows[0].find_all(['th', 'td'])) if row_count > 0 else 0
                if row_count == 0 or col_count == 0: return
                
                # 创建Word表格
                table = doc.add_table(rows=row_count, cols=col_count)
                table.alignment = WD_TABLE_ALIGNMENT.CENTER
                for r_idx, row in enumerate(rows):
                    cells = row.find_all(['th', 'td'])
                    for c_idx, cell in enumerate(cells):
                        tc = table.cell(r_idx, c_idx)
                        tc.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
                        p = tc.paragraphs[0]
                        parse_inline_content(cell, p)
                        # 表头样式加粗
                        if cell.name == 'th':
                            for run in p.runs:
                                run.font.bold = True
            
            # 新增:处理代码块
            elif node.name == 'pre':
                code_node = node.find('code')
                if code_node:
                    p = doc.add_paragraph()
                    run = p.add_run(code_node.get_text())
                    run.font.name = 'Consolas'  # 代码专用等宽字体
                    run.font.size = Pt(10)
                    run.font.color.rgb = RGBColor(0, 0, 0)  # 黑色
            
            # 新增:处理图片(MD:![描述](图片路径))
            elif node.name == 'img':
                img_src = node.get('src', '')
                img_alt = node.get('alt', '图片')
                if os.path.exists(img_src):
                    try:
                        doc.add_picture(img_src, width=Inches(4))  # 限制图片宽度
                        p = doc.add_paragraph(img_alt)
                        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
                    except Exception as e:
                        doc.add_paragraph(f"图片加载失败:{img_src} | 错误:{str(e)}")
                else:
                    doc.add_paragraph(f"图片不存在:{img_src}(描述:{img_alt})")
        
            for child in node.children:
                if child.name:
                    parse_html_node(child, doc)
        
        def parse_inline_content(node, paragraph):
            # 行内元素(加粗、斜体、超链接)- 同基础版
            for content in node.contents:
                if isinstance(content, str):
                    run = paragraph.add_run(content)
                    run.font.name = '宋体'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
                    run.font.size = Pt(12)
                elif content.name == 'strong':
                    run = paragraph.add_run(content.get_text())
                    run.font.bold = True
                elif content.name == 'em':
                    run = paragraph.add_run(content.get_text())
                    run.font.italic = True
                elif content.name == 'a':
                    text = content.get_text()
                    link = content.get('href', '')
                    run = paragraph.add_run(f"{text}({link})")
        
        # ------------------- 调用示例 -------------------
        if __name__ == "__main__":
            INPUT_MD_FILE = "./test.md"  # 替换为你的MD文件路径
            markdown_to_word(INPUT_MD_FILE)
        

        将需要转换的 Markdown 文件(如 test.md)放在代码同目录下,或填写绝对路径(如 C:/文档/我的笔记.md)。

        在代码末尾的 if __name__ == "__main__": 块中,替换 INPUT_MD_FILE 为你的 MD 文件路径:

        INPUT_MD_FILE = "./你的文件.md"  # 相对路径
        # 或
        INPUT_MD_FILE = "D:/project/note.md"  # 绝对路径
        

        直接执行该 Python 文件,终端输出 转换成功! 即完成,转换后的 Word 文件会保存在同目录(默认)或你指定的路径下。

        坑1:中文乱码/字体异常

        • 解决方案:为所有文字节点指定中文字体(宋体/黑体),通过 qn('w:eastAsia') 强制生效;
        • 核心代码:run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')

        坑2:Markdown 语法解析不全

        解决方案:启用 python-markdown 的扩展库(extra/codehilite),支持表格、代码块、脚注等扩展语法。

        坑3:列表嵌套/格式错乱

        解决方案:用 recursive=False 限制列表子节点解析层级,配合 Word 内置的 List Bullet/List Number 样式,保证列表格式统一。

        坑4:图片加载失败

        解决方案:增加图片路径校验,若路径不存在则在 Word 中提示错误信息,避免程序崩溃。

        • 标题:# 一级标题 ~ ###### 六级标题
        • 段落:自然换行/空行分隔
        • 加粗:**加粗内容**
        • 斜体:*斜体内容*
        • 无序列表:- 列表项1 / * 列表项1
        • 有序列表:1. 列表项1 / 2. 列表项2
        • 超链接:[链接文本](链接地址)

        • 表格:| 表头1 | 表头2 | + |---|---| + | 内容1 | 内容2 |
        • 代码块:python 代码内容
        • 图片:![图片描述](图片本地路径)
        • 换行:n<br>

        如果需要极简、无代码的转换方案,推荐使用成熟工具 pandoc,比手动开发的脚本支持的语法更全、兼容性更强:

        • Windows:winget install pandoc
        • Mac:brew install pandoc
        • Linux:sudo apt install pandoc

        pandoc -s 你的文件.md -o 输出文件.docx

        优势:支持所有 Markdown 语法(公式、脚注、目录、引用等),无需编写代码,转换速度极快。

        • 手动开发方案(python-markdown + python-docx):适合需要自定义转换规则(如字体、样式、格式)的场景,代码可灵活扩展;
        • 工具方案(pandoc):适合快速批量转换,无需开发,开箱即用,兼容性最优;
        • 核心避坑:处理中文时必须指定中文字体 + UTF-8 编码,解析列表时限制递归层级。

        两种方案均可满足 Markdown → Word 的转换需求,可根据实际场景选择。

        到此这篇关于python将Markdown文件格式转为Word文档的示例代码的文章就介绍到这了,更多相关python Markdown转Word内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

        您可能感兴趣的文章:

        • Python将Markdown文件转换为Word(docx)完整教学
        • Python轻松实现Word到Markdown的转换
        • Python实现将Markdown转为Word、HTML、PDF、PNG和JPG
        • 基于Python实现Markdown与Word高保真互转
        • 使用Python实现Markdown转Word工具
        • 使用Python将Markdown文件转换为Word的三种方法
        • Python实现快速提取Word表格并转Markdown
        • Python使用pypandoc将markdown文件和LaTex公式转为word
        • 使用Python构建Markdown转Word文档转换器

        站内搜索