如何使用Python实现包含图片的邮件合并及文档合并?
解决包含图片的邮件合并与文档合并问题
方案1:使用ODF格式 + python-odf库
ODF(OpenDocument Format)的结构更易操作,python-odf库对图片、文本的支持更稳定,不会像xml.etree那样容易损坏文件,是替代docx格式的可靠选择。
操作步骤与代码示例
- 安装依赖:
pip install odfpy
- 合并含图片的ODT文档:
from odf.opendocument import load, OpenDocumentText from odf.text import P, H from odf.draw import Frame def merge_odt_files(source_path, target_path, output_path): # 加载源文档与目标文档 source_doc = load(source_path) target_doc = load(target_path) # 获取目标文档正文节点 target_body = target_doc.getElementsByType(OpenDocumentText)[0].body # 遍历源文档所有元素并复制到目标文档 for element in source_doc.getElementsByType(OpenDocumentText)[0].body.childNodes: # 复制段落、标题 if isinstance(element, (P, H)): target_body.appendChild(element.cloneNode(deep=True)) # 复制图片框架(包含图片资源) elif isinstance(element, Frame): cloned_frame = element.cloneNode(deep=True) target_body.appendChild(cloned_frame) # 保存合并结果 target_doc.save(output_path) # 调用示例 merge_odt_files("source_with_images.odt", "target_template.odt", "merged_result.odt")
- ODT格式邮件合并:
def odt_mail_merge(template_path, data_list, output_prefix): for idx, data in enumerate(data_list): doc = load(template_path) body = doc.getElementsByType(OpenDocumentText)[0].body # 遍历段落替换占位符(模板中用{{key}}标记) for para in body.getElementsByType(P): for text_node in para.childNodes: if hasattr(text_node, 'data'): for key, value in data.items(): text_node.data = text_node.data.replace(f"{{{{{key}}}}}", value) doc.save(f"{output_prefix}_{idx+1}.odt") # 测试数据 mail_data = [ {"name": "Alice", "project": "AI Toolkit"}, {"name": "Bob", "project": "Data Pipeline"} ] # 执行邮件合并 odt_mail_merge("mail_template.odt", mail_data, "output_mail")
方案2:Windows环境下调用Word COM接口(最稳定)
如果运行环境是Windows,直接调用Microsoft Word的原生功能是最优解——完美保留图片、格式,邮件合并功能成熟,完全规避第三方库的兼容性问题。
操作步骤与代码示例
- 安装依赖:
pip install pywin32
- 合并含图片的DOCX文档:
import win32com.client as win32 def merge_word_files(source_paths, output_path): word = win32.gencache.EnsureDispatch('Word.Application') word.Visible = False # 后台运行不显示窗口 # 创建空文档作为合并容器 merged_doc = word.Documents.Add() for path in source_paths: source_doc = word.Documents.Open(path) # 复制源文档全部内容 source_doc.Content.Copy() # 粘贴到合并文档末尾 merged_doc.Content.Paste() # 插入分页符(可选) merged_doc.Content.InsertBreak(win32.constants.wdPageBreak) source_doc.Close(SaveChanges=False) merged_doc.SaveAs(output_path) merged_doc.Close() word.Quit() # 调用示例 merge_word_files(["doc1.docx", "doc2_with_images.docx"], "merged_word.docx")
- Word原生邮件合并:
def word_mail_merge(template_path, data_path, output_path): word = win32.gencache.EnsureDispatch('Word.Application') word.Visible = False doc = word.Documents.Open(template_path) # 加载数据源(支持Excel、CSV等格式,需对应调整Format参数) doc.MailMerge.OpenDataSource( Name=data_path, Format=win32.constants.wdOpenFormatText ) # 合并到新文档 doc.MailMerge.Destination = win32.constants.wdSendToNewDocument doc.MailMerge.Execute() word.ActiveDocument.SaveAs(output_path) doc.Close(SaveChanges=False) word.Quit() # 调用示例(数据源为CSV文件) word_mail_merge("mail_template.docx", "mail_data.csv", "merged_mail.docx")
方案对比
- ODF + python-odf:跨平台,无需依赖Office,适合非Windows环境,但模板制作不如Word直观,需熟悉ODF基本结构。
- Word COM接口:格式、图片支持完美,邮件合并功能成熟,但仅支持Windows,需安装Microsoft Word。
内容的提问来源于stack exchange,提问作者Bob_the_walrus
相关产品推荐
相关产品推荐

