python处理word_用python批量处理word文档

应我家领导要求,开发一个word文档批处理脚本,涉及word文档、excel表格、文件存取、排序与索引、简单GUI等内容,前期针对各分项功能实现写了几篇小文章,现在将总体思路记录一下,作为这个系列的完结篇。

由于针对目标文档进行了很多特定操作,源代码本身不具备通用性,下面主要精讲其中的关键部分。完整代码、示例文档详见:

开发需求:

素材为批量word文档集(docx):位于original文件夹中。文件名为“N.xxxx.docx”(N为数字、xxxx为文档标题)。(见附图)

文件内容为各类新闻报道,排版为标题、正文内容(包括图片)、签名尾行(署名+日期)。(见附图)

需实现的功能包括:建立文档清单,清单内容包括序号、署名、日期、标题。

排序文档清单,署名+日期联合排序,署名按照指定的排序规则表排序(见附图)。

筛选文档,从清单中筛选满足特定要求(比如日期范围)的文档,生成筛选后的清单,并从原始文档集中提取这些文档。

修订文档,将文档重新排版(标题行+空一行+正文段落+签名尾行+空两行),并校订文档中的标点错误(英文标点误用、省略号不准确等)。

合并文档,将筛选、修订后的文档合并为一个统一的文档,保持各子文档的排版格式不变。

图形界面,正逢领导生日,所以除了好用,还要好看,传送门在此:爱coding:心形绘制的小改进:turtle模块original文件夹示例文档内容示例排序规则表.txt

逻辑图设计:

对程序主体逻辑梳理如下。

关键代码实现:清单操作

程序涉及的清单包括:default_database.xls(原始清单,如没有提供则需生成)、all_queued.xls(按照媒体、时间排序后的总清单)、screen_queued.xls(特定年份的清单)。为便于查看,这些清单都要求生成Excel表格。

原始清单(如有)采用xlrd模块读取,所有清单生成则采用xlwt模块。xlrd、xlwt模块基本概念和涉及到的操作在另一篇文章中介绍:

其中重复进行的操作,如excel表格生成(genXls())独立为函数,通过函数调用来实现复用,以减少代码量。

其中比较重要的一点就是对时间格式的处理。日期相关操作采用datetime模块,时间格式转换采用time模块。

word文档、excel表格中文本格式表示的日期:

首先通过正则表达式搜索得到文本格式的日期datestr,然后识别日期分隔符('/', '-'等),并采用time.strptime()从字符串中提取年月日数值,最后通过datetime.datetime()构造日期格式数据。

date_pat = re.compile('\d{4}\D\d{1,2}\D\d{1,2}') # 日期格式的正则表达式YYYYxMMxDD

...

sch = re.search(date_pat, para.text) #提取文本格式的日期

if sch: #如匹配到日期

datestr = para.text[sch.start() : sch.end()]

split = []

for char in datestr: #识别日期分隔符

if char not in digit:

split.append(char)

y, m, d = time.strptime(datestr,

'%Y' + '%s' % split[0] + '%m' + '%s' % split[1] + '%d')[0:3] #提取年月日数值

date = datetime.datetime(y, m, d) #构造datetime日期格式

excel表格中日期格式表示的日期:

从excel中读取的日期是一个浮点数,需采用xlrd.xldate_as_datetime(cell,0)转为datetime.datetime日期格式。

向excel写入日期时,通过ws.write(r, c, content, mf)中的mf(style实例)设置成excel日期格式。

mf = xlwt.XFStyle()

mf.num_format_str = 'yyyy/mm/dd' #设置日期格式为:年/月/日

ws.write(r, c, content, mf)

另外一点就是excel表格中的文档清单排序,包括按媒体(排序规则表.txt)和按日期进行排序。特别是按媒体名称排序,为避免前序操作改变了后续步骤的索引位置,采用倒序的冒泡法排序,具体方法见:

文档操作

文档操作包括:对单篇文档的文字、格式修订;多篇文档合成为一个总文档。

文档操作整体采用docx模块,其中文字修订采用正则表达式来搜索(string、re模块)。docx模块基本概念和涉及到的操作在另一篇文章中介绍:

其中重复进行的操作,如文档格式设置(setdocStyle())、文本内容修订(refText())独立为函数,通过函数调用来实现复用,以减少代码量。

setdocStyle()直接调用可设置为默认格式(包括字体、字体大小、首行缩进、段前间距、段后间距、行距等),也可通过关键字参数修改格式。

refText()可实现对所有文本内容的检查和修正,目前实现了中英文标点符号的修订、回引号缺失修正、省略号错误提示。

word文档图片提取值得详细说明一下,图片提取采用了zipfile模块。

大家知道docx模块可通过doc.inline_shapes提取所有内联图形,也即嵌入方式插入文档的图形。但是,其他方式(比如浮于文字上方、四周环绕等)的图片不会包括在doc.inline_shapes中,这些图片只能通过doc.paragraphs[n].runs[m].element.drawing_lst来识别。

docx格式本质是xml文件的压缩包,将docx文档后缀名改为zip,然后解压缩,就可以得到如下图所示的内容,其中word文件夹为文档主要信息储存位置,该文件夹中的media文件夹即包括所有图片内容(按文档中的顺序命名)。docx文档解压缩后的内容word文件夹打开后的内容

因此,本文通过块中的drawing_lst来判断文档中是否有图片,对于有图片的文档,采用zipfile解压缩提取media文件夹中的所有图片。实例代码如下。

# 指定用于提取图片的临时zip文件、文件夹

temp_zip = 'temp.zip'

temp_dir = 'temp'

fig_unloaded = True #记录图片是否已经载入

...

# doc.inline_shapes无法识别非嵌入式图片,故直接从段落块判定有无图

if run.element.drawing_lst:

if fig_unloaded: #如本doc还未载入图片,此处载入

silence = shutil.copy(os.path.join(src_dir, doc_name), temp_zip)

f = zipfile.ZipFile(temp_zip)

for file in f.namelist():

if file.startswith('word/media/image'):

silence = f.extract(file, temp_dir)

f.close()

img_dir = os.path.split(silence)[0]

img_list = os.listdir(img_dir) #所有图片路径的清单

fig_unloaded = False #本文档图片已载入,不再重复载入

...

# 临时文件清理

if os.path.exists(temp_zip):

os.remove(temp_zip)

if os.path.exists(temp_dir):

shutil.rmtree(temp_dir)

图片插入word文档,则采用doc.paragraphs[n].runs[m].add_picture()完成,不再细讲。

欢迎关注我的公众号(zz-icoding),以后将逐步整理成系列化的python学习资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值