近日有工作上的需求,需要梳理数据元目录中的多个数据项,数据项条目可能达到1000多个,可以说这个工作量非常巨大,源文件是 word 版本的,无法进行筛选和标记(即使用颜色或者字体去标记之后,每次也需要肉眼去看某一项到底有没有梳理过),如果是 excel 版本就不一样了,已梳理和未梳理的可以很简单的完成分类,并且和其他文件进行比对,用以核实是否已经梳理过。
问题来了:如何进行 word 文本转 excel?
word 版本文件是这样的:
可以看出,文件具有4层目录,每一个数据项又包含了定义、英文缩写、数据格式、说明等内容。
python-docx 读取失败
想用 Python 处理 docx 自然就想到了 python-docx
,这就去试试。
首先安装 python-docx
包
pip install python-docx -i https://pypi.tuna.tsinghua.edu.cn/simple
然后用 python-docx
识别了一下文件内容
from docx import Document
doc=Document(r'.demo.docx')
for i, paragraph in enumerate(doc.paragraphs):
print(i,'------------', paragraph.text)
你有没有发现他居然把目录编号给丢弃了。。。
有点难以接受,随后我去翻阅了官方接口文档,也没有读取 heading
的方法,查阅了好久资料也没找到更好的包,问题搁置。。。
PyPDF2 读取失败
某天吃饭的时候,我突然想到能不能用 pdf 去试试,因为 word 文件的目录编号是格式上的,而 pdf 文件内容是所见即所得。
然后,我又去研究 pdf 内容读取,首先发现了 PyPDF2
,
但是他读取中文 pdf 都是乱码,找了好久也没找到设置编码的方法,遂放弃。。。
pdfplumber 读取成功并写入txt
最后,我又发现了 pdfplumber
他可以完美解析中文,太棒了
查看 page_text
数据类型,发现是 str ,就是返回的全部的文本内容,是一个很长很长的字符串,这种不方便进行后续处理。可以把 page_text
内容写入 txt,然后再逐行读取。
import pdfplumber
file_path = r'.demo.pdf'
with pdfplumber.open(file_path) as pdf:
pages = pdf.pages
content = ''
for i in range(len(pages)):
page_text = pages[i].extract_text()
if page_text:
content = content page_text
with open('tmp.txt',mode='w ') as file:
file.write(content)
file.close
逐行读取txt
代码语言:javascript复制f = open(".tmp.txt")
file = f.readlines()
使用正则表达式识别文本、OrderedDict封装文本
定义正则表达式 pattern
这里定义多个 pattern
表达式用于识别标题和文本内容
title_level1=re.compile("d.[^0-9]")
title_level2=re.compile("d.d[^.0-9]")
title_level3=re.compile("d.d.d[^.0-9]")
title_level4=re.compile("d.d.d.d[^.0-9]")
content1 = re.compile("定义")
content2 = re.compile("英文缩写")
content3 = re.compile("数据格式")
content4 = re.compile("说明")
定义9个 OrderedDict
这里定义9个 OrderedDict
用于封装标题和文本内容,key_title
是最外层的 OrderedDict
,title1 是第一个层级的key,后续所有内容封装到一个 OrderedDict
,title2 是第二个层级的key,后续所有内容封装到一个 OrderedDict
,后续各层原理一致
key_title = OrderedDict()
key_title1 = OrderedDict()
key_title2 = OrderedDict()
key_title3 = OrderedDict()
key_title4 = OrderedDict()
key_content1 = OrderedDict()
key_content2 = OrderedDict()
key_content3 = OrderedDict()
key_content4 = OrderedDict()
逐行进行正则识别,写入 OrderedDict
代码语言:javascript复制for each in file:
if title_level1.match(each):
key_title1 = key_title.setdefault(each, OrderedDict())
if title_level2.match(each):
key_title2 = key_title1.setdefault(each, OrderedDict())
if title_level3.match(each):
key_title3 = key_title2.setdefault(each, OrderedDict())
if title_level4.match(each):
key_title4 = key_title3.setdefault(each, OrderedDict())
if content1.match(each):
key_content1 = key_title4.setdefault(each, OrderedDict())
if content2.match(each):
key_content2 = key_content1.setdefault(each, OrderedDict())
if content3.match(each):
key_content3 = key_content2.setdefault(each, OrderedDict())
if content4.match(each):
key_content4 = key_content3.setdefault(each, [])
解析 OrderedDict 写入xlsx
代码语言:javascript复制result=[]
for title1, title2X in key_title.items():
for title2, title3X in title2X.items():
for title3, title4X in title3X.items():
for title4, content_a in title4X.items():
for content_a1, content_b in content_a.items():
for content_b1, content_c in content_b.items():
for content_c1, content_d in content_c.items():
for content_d1 in content_d.items():
result.append([title1, title2, title3, title4, content_a1[3:], content_b1[5:], content_c1[5:], content_d1[0][3:]])
df = pd.DataFrame(result, columns=['title1', 'title2', 'title3', 'title4', '定义', '英文缩写', '数据格式', '说明'])
df.to_excel("result.xlsx")
最终文件内容如下: