目的

由于商业原因,最近要实现一个功能,就是word文档 (docx格式)的批量文本替换,把docx中的商标名换成自己的,替换过程中要保留word文档的样式。
在网上搜寻多种方案,有 python-docx, 有 apache poi, 均不符合我的要求,主要是 这些库 解析docx文档 能力有限,文档不全,而且有的内容无法识别到,
有的即使替换了,样式也乱了,下面是我自己的方案,效果堪称完美。

思路

docx 文件其实是zip文件,在windows上,我们将docx文件重命名为zip文件,解压,即可得到下面的文件:

docx文件解压后的内容

可以看到 docx文件本质是 资源文件 + xml 文件的集合,而 word文档中的文字 都在 word/document.xml 中。
我们只要替换这个文件,再重新压缩为zip,再改成.docx格式 ,即可实现替换。

代码实现

  1. import zipfile
  2. import shutil
  3. import os
  4.  
  5. import file_util
  6.  
  7. ”’
  8. input_f 输入文件路径
  9. out_f 输出文件路径
  10. ”’
  11.  
  12.  
  13. def replace_text(input_f, out_f):
  14. owd = os.getcwd()
  15. # 将淘宝替换为京东
  16. replacements = {
  17. ‘淘宝’: ‘京东’,
  18. }
  19. tmp_dir = “D:\\BaiduNetdiskDownload\\tmp\\”
  20. try:
  21. filename = input_f.split(“\\”)[-1]
  22. os.chdir(tmp_dir)
  23. shutil.copy(input_f, tmp_dir) # 复制到临时目录
  24. copy_file = os.path.join(tmp_dir, filename)
  25. zip_file = copy_file.replace(“.docx”, “.zip”)
  26. os.rename(copy_file, zip_file)
  27. # 解压文件
  28. with zipfile.ZipFile(zip_file, “r”) as zip_ref:
  29. zip_ref.extractall(tmp_dir)
  30. os.remove(zip_file)
  31. # 替换文本
  32. with open(‘word\\document.xml’, ‘r’, encoding=“utf8”) as file:
  33. str = file.read()
  34. for k, v in replacements.items():
  35. str = str.replace(k, v)
  36. text_file = open(“out.xml”, “w”, encoding=“utf8”)
  37. n = text_file.write(str)
  38. text_file.close()
  39.  
  40. # close input and output files
  41. os.remove(“word\\document.xml”)
  42. os.rename(“out.xml”, “word\\document.xml”)
  43. # 重命名文件
  44. dst_zip_file_name = filename.replace(“.docx”, “.zip”)
  45. shutil.make_archive(filename.replace(“.docx”, “”), ‘zip’, tmp_dir)
  46. os.rename(dst_zip_file_name, out_f)
  47. except Exception as e:
  48. pass
  49. finally:
  50. # 将临时目录清空
  51. file_util.clean_dir(tmp_dir)
  52. os.chdir(owd)
  53.