根据日记记载,今天(2021年03月06日)我面临着一个来自他人出给我的难题。。并写了一下午的代码。。因此想要再次将这个痛苦的过程记录下来。。一遍将来我什么时候需要相同的功能不用自己再痛苦一次

准备阶段

安装LibreOffice

前往官网下载:LibreOffice下载官网:https://www.libreoffice.org/download/download/

安装python-docx

使用pip安装

1
pip install python-docx

使用conda安装

1
2
conda activate env(因为我这里关闭了默认启动conda。。所以需要先激活一下相关的环境)
conda install -c conda-forge python-docx

使用方法

首先将待替换文件拷贝到py文件目录下的file文件夹下(或者这里可以更改源码中的file_located变量)

然后运行程序即可

本代码会遍历所有file文件夹中的所有文件,检查文件类型,如果非word文档则会直接拷贝到./file/替换结果/位置下的对应文件路径中,如果是word文档自会调用LibreOffice工具进行文档类型转换,并将转换后的文件保存到./file/docx/路径下。最后遍历docx目录下的所有文件,并调用python-docx包对word文档进行查找替换和保存,保存到./file/替换结果/目录下。

待程序运行结束后,所有文档将会保存在./file/替换结果/目录下。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# %% 路径配置区域

# 文件所在文件夹
file_located = "./file/"

# 替换结果的路径
result_file_path = file_located + "/替换结果/"

# 源文件路径
source_path = file_located

# 转换为docx文件的路径
docx_path = file_located + "/docx/"

# 待替换列表
replace_list = [["XX物联网科技有限公司", "YYY智能科技有限公司"],
["JXKJ", "JGKJ"],
["王铮", "王峥"]]

# %% 方法配置区域
# coding:utf-8

import sys
from docx import Document
import os #用于获取目标文件所在路径
import subprocess

def create_if_not_exist(path):
'''
此函数用于判断路径是否存在,如果路径不存在则创建对应路径
最后返回传入路径,因此调用时候可直接放在路径中作为参数传入
'''
if not os.path.exists(path):
os.makedirs(path)
return path

def info_update(doc,old_info, new_info):
'''此函数用于批量替换合同中需要替换的信息
doc:文件
old_info和new_info:原文字和需要替换的新文字
'''
#读取段落中的所有run,找到需替换的信息进行替换
for para in doc.paragraphs: #
for p in doc.paragraphs:
if old_info in p.text:
inline = p.runs
for i in inline:
if old_info in i.text:
text = i.text.replace(old_info, new_info)
i.text = text
#读取表格中的所有单元格,找到需替换的信息进行替换
for t in doc.tables:
for r in t.rows:
mycell = r.cells
for c in mycell:
for p in c.paragraphs:
if old_info in p.text:
inline = p.runs
for i in inline:
if old_info in i.text:
text = i.text.replace(old_info, new_info)
i.text = text
# 不改变格式的情况下修改head的表格内容(我是没想明白还有人有这种需求(在页眉中插入表格)。。简直是变态)
for section in doc.sections:
for t in section.header.tables:
for r in t.rows:
mycell = r.cells
for c in mycell:
for p in c.paragraphs:
if old_info in p.text:
inline = p.runs
for i in inline:
if old_info in i.text:
text = i.text.replace(old_info, new_info)
i.text = text

def doc2docx(source_path, destination_path, result_file_path):
'''
用于将传入的路径中所有doc文件转换为docx文件,并且其他文件直接复制到目标文件夹
'''
g = os.walk(source_path)
for path,dir_list,file_list in g:
for file_name in file_list:
file = (os.path.join(path, file_name))
if(not (file.endswith(".doc") or file.endswith(".docx"))): # 非word文件直接复制到目标文件夹中相应路径下
tmp_path = create_if_not_exist(result_file_path + path[len(source_path):] + '/') + file_name
os.system('cp "' + file + '" "' + tmp_path + '"') # 调用shell命令 进行移动
print("移动文件到:" + tmp_path)
continue
output = subprocess.check_output(["/Applications/LibreOffice.app/Contents/MacOS/soffice","--headless","--convert-to","docx",file,"--outdir",destination_path + path[len(source_path):]])
print ("转换文件:" + file + "的格式")

# %% 获取转换后的文件目录
def get_docx_files_paths(docx_path):
'''
根据给定的文件夹路径遍历所有子文件夹,并返回一个list保存有所有的docx文件路径
'''
files=[]
g = os.walk(docx_path)
for path,dir_list,file_list in g:
for file_name in file_list:
if(file_name.endswith(".docx")):
file = (os.path.join(path, file_name))
print (file)
files.append(file)
return files

# 执行替换
def replace_with_list(files_path, replace_list):
'''
循环遍历传入的文件路径list,
循环变更每一个文件的替换list中的替换内容
'''
print("开始内容替换")
for file_path in files_path:
doc = Document(file_path)
for replace in replace_list:
info_update(doc,replace[0],replace[1])
file_path = os.path.join(result_file_path, file_path[len(docx_path):])
path = create_if_not_exist(file_path[:-len(file_path.split('/')[-1])])
doc.save(file_path)
print("{}替换完成".format(file_path))

# %%
def main():
doc2docx(source_path, docx_path, result_file_path)
replace_with_list(get_docx_files_paths(docx_path), replace_list)

if __name__ == "__main__":
main()

参考

【知乎|用Python批量替换多个Word文件中的文字】: https://zhuanlan.zhihu.com/p/64052960

【知乎|在Mac下,如何批量地把 .doc 文件转为 .docx 文件?】: https://www.zhihu.com/question/278614707/answer/409654085

【Ops Blog | 孙高猛|Mac用Python批量将doc转换为docx】: https://opsolo.com/python/libreoffice-doc-to-docx/

【CSDN|Python:错误FileNotFoundError: [Errno 2] No such file or directory: 'objects/epsilon.pkl】: https://blog.csdn.net/lvsehaiyang1993/article/details/80615549

【知乎|python-docx模块中如何实现对WORD的查找和替换功能?】: https://www.zhihu.com/question/64235925