在技术写作和博客创作中,Markdown因其简洁的语法和跨平台兼容性备受青睐。然而,从Word文档转换到Markdown往往面临格式丢失、图片处理繁琐等问题。本文将介绍一款自主开发的Python工具docx2md
,实现Word文档(包含文本、图片、表格)到Markdown的自动化转换,大幅提升内容迁移效率。
下划线
兼容images
文件夹并自动添加Markdown图片引用基于Tkinter开发的图形化界面(GUI),无需记忆命令行参数:
pip install python-docx>=0.8.10 # 核心文档解析库
提示:Tkinter为Python内置标准库,无需额外安装
python docx2md.py
首次运行会显示极简主窗口(自动隐藏,仅保留对话框)
在弹出的文件对话框中选择需要转换的.docx文档(支持中文文件名)
目标目录/
├─ 原文件名.md # 生成的Markdown文件
└─ images/ # 图片资源文件夹
├─ image_0.png
├─ image_1.png
└─ ...
Heading 1 → # 标题1
Heading 2 → ## 标题2
...
Word格式 | Markdown |
---|---|
加粗 | 加粗文本 |
斜体 | 斜体文本 |
下划线 | 下划线文本 |
自动生成:
表头1 | 表头2 |
---|---|
内容1 | 内容2 |
import os
import re
import sys
import docx
import base64
import tkinter as tk
from tkinter import filedialog, messagebox
from docx.shared import Pt
from docx.oxml.ns import qn
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.enum.style import WD_STYLE_TYPE
from docx.opc.constants import RELATIONSHIP_TYPE as RT
from docx.oxml import OxmlElement
def extract_images(doc):
"""从Word文档中提取所有图片"""
image_dict = {}
image_index = 0
# 遍历文档中的关系
for rel in doc.part.rels.values():
# 检查关系类型是否为图片
if rel.reltype == RT.IMAGE:
# 获取图片数据
image_data = rel.target_part.blob
# 生成图片文件名
image_name = f"image_{image_index}.png"
image_index += 1
# 存储图片数据和关系ID
image_dict[rel.rId] = {
"data": image_data,
"name": image_name
}
return image_dict
def save_images(image_dict, output_dir):
"""保存提取的图片到指定目录"""
img_dir = os.path.join(output_dir, "images")
os.makedirs(img_dir, exist_ok=True)
for rel_id, img_info in image_dict.items():
img_path = os.path.join(img_dir, img_info["name"])
with open(img_path, "wb") as f:
f.write(img_info["data"])
return img_dir
def convert_paragraph_to_markdown(paragraph, image_dict):
"""将段落转换为Markdown格式"""
md_text = ""
# 处理段落样式(标题识别)
if paragraph.style.name.startswith('Heading'):
level = paragraph.style.name.replace('Heading ', '')
try:
level = int(level)
md_text += "#" * level + " "
except ValueError:
pass # 处理异常样式
# 处理段落中的文本和图片
for run in paragraph.runs:
text = run.text
# 加粗处理
if run.bold:
text = f"**{text}**"
# 斜体处理
if run.italic:
text = f"*{text}*"
# 下划线处理(Markdown不原生支持,使用HTML标签)
if run.underline:
text = f"{text}"
md_text += text
# 检查段落是否包含图片(通过关系ID在XML中存在性判断)
for rel_id, img_info in image_dict.items():
if rel_id in paragraph._element.xml:
md_text += f"\n\n![{img_info['name']}](images/{img_info['name']})\n\n"
return md_text
def convert_table_to_markdown(table):
"""将表格转换为Markdown格式"""
md_table = "\n"
# 处理表头
header_row = table.rows[0]
md_table += "|" + "|".join([cell.text for cell in header_row.cells]) + "|\n"
# 添加分隔行
md_table += "|" + "|".join(["---" for _ in header_row.cells]) + "|\n"
# 处理表格内容行
for row in table.rows[1:]:
md_table += "|" + "|".join([cell.text for cell in row.cells]) + "|\n"
return md_table + "\n"
def docx_to_markdown(docx_path, output_dir=None):
"""核心转换函数:Word文档转Markdown"""
if output_dir is None:
output_dir = os.path.dirname(docx_path) # 使用原文件目录
doc = docx.Document(docx_path)
image_dict = extract_images(doc)
# 保存图片(如果有的话)
if image_dict:
save_images(image_dict, output_dir)
# 生成Markdown文件路径
md_filename = os.path.splitext(os.path.basename(docx_path))[0] + ".md"
md_path = os.path.join(output_dir, md_filename)
md_content = ""
# 处理段落
for i, paragraph in enumerate(doc.paragraphs):
try:
md_content += convert_paragraph_to_markdown(paragraph, image_dict) + "\n\n"
except Exception as e:
print(f"段落处理错误({i}): {str(e)}")
continue # 跳过错误段落
# 处理表格
for i, table in enumerate(doc.tables):
try:
md_content += convert_table_to_markdown(table)
except Exception as e:
print(f"表格处理错误({i}): {str(e)}")
continue # 跳过错误表格
# 写入文件
with open(md_path, "w", encoding="utf-8") as f:
f.write(md_content)
return md_path
def main():
# 初始化GUI
root = tk.Tk()
root.title("Word转Markdown工具")
root.geometry("500x300")
root.withdraw() # 隐藏主窗口,仅显示对话框
# 选择Word文件
docx_path = filedialog.askopenfilename(
title="选择待转换的Word文档",
filetypes=[("Word文档", "*.docx"), ("所有文件", "*.*")]
)
if not docx_path:
sys.exit(0) # 用户取消操作
if not os.path.exists(docx_path):
messagebox.showerror("错误", f"文件不存在:{docx_path}")
sys.exit(1)
# 选择输出目录
output_dir = filedialog.askdirectory(
title="选择输出目录(取消则使用原文件目录)"
)
if not output_dir:
output_dir = None # 使用默认目录
# 执行转换
try:
md_path = docx_to_markdown(docx_path, output_dir)
messagebox.showinfo("成功", f"转换完成!\n保存路径:{md_path}")
except Exception as e:
messagebox.showerror("错误", f"转换失败:{str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()
通过这款工具,我们可以快速将Word文档转换为结构清晰的Markdown文件,尤其适合技术文档迁移、博客内容复用等场景。建议在复杂文档转换后进行格式校验,确保最佳显示效果。欢迎在评论区分享你的使用体验或提出改进建议!