python將Markdown文件格式轉(zhuǎn)為Word文檔的示例代碼
一、核心方案說明
要實(shí)現(xiàn) Markdown 文件 → Word(.docx) 文件 的格式轉(zhuǎn)換,核心思路是:
- 先用
python-markdown庫把 Markdown 文本/文件解析成 HTML 格式; - 再用
python-docx庫將解析后的 HTML 內(nèi)容,逐節(jié)點(diǎn)渲染到 Word 文檔中,完成最終轉(zhuǎn)換。
二、完整環(huán)境安裝(一鍵執(zhí)行)
該方案依賴 3 個(gè)核心庫,直接在終端執(zhí)行以下命令安裝所有依賴:
pip install python-markdown python-docx beautifulsoup4
python-markdown:核心 Markdown 解析庫,負(fù)責(zé) MD → HTML;python-docx:核心 Word 操作庫,負(fù)責(zé)生成/編輯 .docx 文檔;beautifulsoup4:輔助解析 HTML 節(jié)點(diǎn),方便精準(zhǔn)提取內(nèi)容渲染到 Word。
三、完整可運(yùn)行代碼(直接復(fù)用)
版本1:基礎(chǔ)版(支持絕大多數(shù) MD 語法,滿足日常需求)
支持標(biāo)題(1-6級(jí))、段落、加粗、斜體、有序列表、無序列表、超鏈接、圖片、換行等核心語法,代碼可直接復(fù)制運(yùn)行:
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文件轉(zhuǎn)Word文檔核心函數(shù)
:param md_file_path: 源Markdown文件路徑(必填,如:./test.md)
:param docx_file_path: 輸出Word文件路徑(可選,默認(rèn)同目錄同名.docx)
"""
# 1. 校驗(yàn)源文件是否存在
if not os.path.exists(md_file_path):
print(f"錯(cuò)誤:源文件 {md_file_path} 不存在!")
return
# 2. 默認(rèn)輸出路徑(同目錄、同名,后綴替換為.docx)
if docx_file_path is None:
docx_file_path = os.path.splitext(md_file_path)[0] + ".docx"
# 3. 讀取Markdown文件內(nèi)容(指定UTF-8編碼,避免中文亂碼)
with open(md_file_path, "r", encoding="utf-8") as f:
md_content = f.read()
# 4. Markdown → HTML(啟用擴(kuò)展,支持更完整語法)
html_content = markdown.markdown(
md_content,
extensions=[
'extra', # 支持表格、代碼塊、腳注等擴(kuò)展語法
'sane_lists', # 優(yōu)化列表解析規(guī)則
'nl2br' # 換行符\n轉(zhuǎn)為HTML的<br>標(biāo)簽
],
extension_configs={}
)
# 5. 初始化Word文檔對(duì)象
doc = Document()
# 6. 全局樣式配置(統(tǒng)一字體、避免中文宋體異常)
doc.styles['Normal'].font.name = '宋體'
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '宋體')
doc.styles['Normal'].font.size = Pt(12) # 正文字號(hào)12號(hào)
# 7. 解析HTML并渲染到Word
soup = BeautifulSoup(html_content, "html.parser")
parse_html_node(soup, doc)
# 8. 保存Word文檔
doc.save(docx_file_path)
print(f"轉(zhuǎn)換成功!Word文件已保存至:{docx_file_path}")
def parse_html_node(node, doc):
"""遞歸解析HTML節(jié)點(diǎn),映射為Word對(duì)應(yīng)樣式"""
# 處理標(biāo)題(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))
# 標(biāo)題樣式:字號(hào)隨級(jí)別遞減,加粗
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()
# 遞歸處理子節(jié)點(diǎn)(兼容嵌套結(jié)構(gòu))
for child in node.children:
if child.name:
parse_html_node(child, doc)
def parse_inline_content(node, paragraph):
"""解析行內(nèi)元素(加粗、斜體、超鏈接等),添加到指定段落"""
for content in node.contents:
if isinstance(content, str):
# 純文本內(nèi)容
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:**內(nèi)容**)
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:*內(nèi)容*)
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'), '宋體')
# ------------------- 調(diào)用示例 -------------------
if __name__ == "__main__":
# 替換為你的Markdown文件路徑(相對(duì)路徑/絕對(duì)路徑均可)
INPUT_MD_FILE = "./test.md"
# 可選:指定輸出Word路徑,如 "./轉(zhuǎn)換結(jié)果.docx"
OUTPUT_DOCX_FILE = None
markdown_to_word(INPUT_MD_FILE, OUTPUT_DOCX_FILE)
版本2:增強(qiáng)版(額外支持 表格、代碼塊、圖片 語法)
日常使用中表格、代碼塊、圖片是高頻 MD 語法,在基礎(chǔ)版上擴(kuò)展該能力,滿足更復(fù)雜的轉(zhuǎn)換需求:
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"錯(cuò)誤:源文件 {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()
# 啟用表格、代碼塊擴(kuò)展
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"轉(zhuǎn)換成功!Word文件已保存至:{docx_file_path}")
def parse_html_node(node, doc):
# 基礎(chǔ)節(jié)點(diǎn)(標(biāo)題、段落、列表)- 同基礎(chǔ)版,此處省略,完整代碼包含
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
# 創(chuàng)建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} | 錯(cuò)誤:{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):
# 行內(nèi)元素(加粗、斜體、超鏈接)- 同基礎(chǔ)版
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})")
# ------------------- 調(diào)用示例 -------------------
if __name__ == "__main__":
INPUT_MD_FILE = "./test.md" # 替換為你的MD文件路徑
markdown_to_word(INPUT_MD_FILE)
四、使用方法(3步極簡操作)
步驟1:準(zhǔn)備源文件
將需要轉(zhuǎn)換的 Markdown 文件(如 test.md)放在代碼同目錄下,或填寫絕對(duì)路徑(如 C:/文檔/我的筆記.md)。
步驟2:修改文件路徑
在代碼末尾的 if __name__ == "__main__": 塊中,替換 INPUT_MD_FILE 為你的 MD 文件路徑:
INPUT_MD_FILE = "./你的文件.md" # 相對(duì)路徑 # 或 INPUT_MD_FILE = "D:/project/note.md" # 絕對(duì)路徑
步驟3:運(yùn)行代碼
直接執(zhí)行該 Python 文件,終端輸出 轉(zhuǎn)換成功! 即完成,轉(zhuǎn)換后的 Word 文件會(huì)保存在同目錄(默認(rèn))或你指定的路徑下。
五、關(guān)鍵優(yōu)化點(diǎn)(解決常見坑)
坑1:中文亂碼/字體異常
- 解決方案:為所有文字節(jié)點(diǎn)指定中文字體(宋體/黑體),通過
qn('w:eastAsia')強(qiáng)制生效; - 核心代碼:
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋體')。
坑2:Markdown 語法解析不全
解決方案:啟用 python-markdown 的擴(kuò)展庫(extra/codehilite),支持表格、代碼塊、腳注等擴(kuò)展語法。
坑3:列表嵌套/格式錯(cuò)亂
解決方案:用 recursive=False 限制列表子節(jié)點(diǎn)解析層級(jí),配合 Word 內(nèi)置的 List Bullet/List Number 樣式,保證列表格式統(tǒng)一。
坑4:圖片加載失敗
解決方案:增加圖片路徑校驗(yàn),若路徑不存在則在 Word 中提示錯(cuò)誤信息,避免程序崩潰。
六、支持的 Markdown 語法清單
基礎(chǔ)語法(基礎(chǔ)版+增強(qiáng)版均支持)
- 標(biāo)題:
# 一級(jí)標(biāo)題~###### 六級(jí)標(biāo)題 - 段落:自然換行/空行分隔
- 加粗:
**加粗內(nèi)容** - 斜體:
*斜體內(nèi)容* - 無序列表:
- 列表項(xiàng)1/* 列表項(xiàng)1 - 有序列表:
1. 列表項(xiàng)1/2. 列表項(xiàng)2 - 超鏈接:
[鏈接文本](鏈接地址)
擴(kuò)展語法(僅增強(qiáng)版支持)
- 表格:
| 表頭1 | 表頭2 |+|---|---|+| 內(nèi)容1 | 內(nèi)容2 | - 代碼塊:
python 代碼內(nèi)容 - 圖片:
 - 換行:
\n或<br>
七、備選方案(更輕量化,一行命令轉(zhuǎn)換)
如果需要極簡、無代碼的轉(zhuǎn)換方案,推薦使用成熟工具 pandoc,比手動(dòng)開發(fā)的腳本支持的語法更全、兼容性更強(qiáng):
1. 安裝 pandoc
- Windows:
winget install pandoc - Mac:
brew install pandoc - Linux:
sudo apt install pandoc
2. 一行命令轉(zhuǎn)換
pandoc -s 你的文件.md -o 輸出文件.docx
優(yōu)勢(shì):支持所有 Markdown 語法(公式、腳注、目錄、引用等),無需編寫代碼,轉(zhuǎn)換速度極快。
總結(jié)
- 手動(dòng)開發(fā)方案(python-markdown + python-docx):適合需要自定義轉(zhuǎn)換規(guī)則(如字體、樣式、格式)的場(chǎng)景,代碼可靈活擴(kuò)展;
- 工具方案(pandoc):適合快速批量轉(zhuǎn)換,無需開發(fā),開箱即用,兼容性最優(yōu);
- 核心避坑:處理中文時(shí)必須指定中文字體 + UTF-8 編碼,解析列表時(shí)限制遞歸層級(jí)。
兩種方案均可滿足 Markdown → Word 的轉(zhuǎn)換需求,可根據(jù)實(shí)際場(chǎng)景選擇。
到此這篇關(guān)于python將Markdown文件格式轉(zhuǎn)為Word文檔的示例代碼的文章就介紹到這了,更多相關(guān)python Markdown轉(zhuǎn)Word內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python將Markdown文件轉(zhuǎn)換為Word(docx)完整教學(xué)
- 基于Python實(shí)現(xiàn)Markdown與Word高保真互轉(zhuǎn)
- 使用Python實(shí)現(xiàn)Markdown轉(zhuǎn)Word工具
- 使用Python將Markdown文件轉(zhuǎn)換為Word的三種方法
- Python實(shí)現(xiàn)快速提取Word表格并轉(zhuǎn)Markdown
- Python使用pypandoc將markdown文件和LaTex公式轉(zhuǎn)為word
- Python將Word文檔轉(zhuǎn)換為Markdown格式
- Python文檔轉(zhuǎn)換之Markdown轉(zhuǎn)Word的高效實(shí)戰(zhàn)指南
相關(guān)文章
python批量修改圖片尺寸,并保存指定路徑的實(shí)現(xiàn)方法
今天小編就為大家分享一篇python批量修改圖片尺寸,并保存指定路徑的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python精確統(tǒng)計(jì)函數(shù)執(zhí)行時(shí)間的多種方法
在軟件開發(fā)中,我們常常需要了解代碼的執(zhí)行效率,本文將介紹 Python中統(tǒng)計(jì) 函數(shù)執(zhí)行時(shí)間 的多種方法,及其適用場(chǎng)景和注意事項(xiàng),需要的朋友可以參考下2026-01-01
Python實(shí)現(xiàn)多圖片格式(PNG/JPG/SVG)到幻燈片的批量轉(zhuǎn)換
這篇文章主要介紹了Python實(shí)現(xiàn)多圖片格式(PNG/JPG/SVG)到幻燈片的批量轉(zhuǎn)換,這篇文章將詳細(xì)介紹如何使用 Python 將各種圖片轉(zhuǎn)換為 PPT 幻燈片,需要的可以了解下2025-11-11
Python實(shí)現(xiàn)Word表格轉(zhuǎn)成Excel表格的示例代碼
這篇文章主要介紹了Python實(shí)現(xiàn)Word表格轉(zhuǎn)成Excel表格的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Python Word實(shí)現(xiàn)批量替換文本并生成副本
這篇文章主要為大家詳細(xì)介紹了Python Word如何實(shí)現(xiàn)批量替換文本并生成副本,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10

