使用python 3.5
我需要找到存储在1997-2003年老式Windows .doc文件中的特定文本,并将其转储到csv中。我的约束是:
a)文档文件位于压缩存档中:我无法写入磁盘/我需要在内存中工作
b)我需要使用正则表达式查找特定文本,因此需要将文档转换为.txt
理想情况下,我可以使用zipfile读取文件,将数据传递到某些doc-to-txt转换器(例如textract),然后在txt上使用正则表达式。可能看起来像
import zipfile
import textract
import re
with zipfile.ZipFile(zip_archive, 'r') as f:
for name in f.namelist():
data = f.read(name)
txt = textract.process(data).decode('utf-8')
#some regex on txt
这当然是行不通的,因为textract(以及其他任何doc-to-txt转换器)的参数是文件路径,而“数据”是字节。使用“名称”作为自变量会给出MissingFileError,这可能是因为zip归档文件没有目录结构,而只是文件名模拟了路径。
是否有任何方法可以仅在内存中通过压缩的doc文件进行正则表达式,而无需提取文件(并因此将它们写入磁盘)?
这两个示例直接从docx存档中读取文件-该文件未提取到磁盘。
如果要以字典和列表的形式对数据进行排序:
import zipfile
import xmltodict
zf = zipfile.ZipFile('/temp/example.docx')
data = xmltodict.parse(zf.open('word/document.xml'))
some_text = data['w:document']['w:body']['w:p'][46]['w:r']['w:t']
print(some_text)
或使用xml.etree.ElementTree。我认为好多了。在相关节点上查找和迭代非常容易。另外,您可以利用XPATH在文档中搜索特定元素。
此示例从.docx文件读取所有文本,并将其写入stdout。比较简单。给re.findall()
的正则表达式提取所有括号内的文本。
import re
import xml.etree.ElementTree as ET
import zipfile
_NS_DICT = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
def get_docx_text(docx_path):
with zipfile.ZipFile(docx_path) as zf:
tree = ET.parse(zf.open('word/document.xml'))
all_text = '\n'.join([n.text for n in tree.findall('.//w:t', _NS_DICT)])
return all_text
if __name__ == '__main__':
text = get_docx_text('/temp/example.docx')
for line in text.splitlines():
print(line)
find_results = re.findall(r"\(.*?\)", text)
print(find_results)
在get_docx_text()
中,此行捕获所有文本:
all_text = '\n'.join([n.text for n in tree.findall('.//w:t', _NS_DICT)])
字符串:'.//w:t'
是一个XPATH表达式,它告诉模块选择单词文档的所有t
(文本)节点。然后列表推导将所有文本连接起来。
一旦从get_docx_text()
返回了文本,就可以应用正则表达式,逐行对其进行迭代,或者执行任何所需的操作。
MS docx文件格式:https://wiki.fileformat.com/word-processing/docx/
xml.ElementTree文档:https://docs.python.org/3/library/xml.etree.elementtree.html?highlight=xml%20etree#module-xml.etree.ElementTree
XPATH:https://docs.python.org/3/library/xml.etree.elementtree.html?highlight=xml%20etree#elementtree-xpath
从该来源借用的第二个示例:https://etienned.github.io/posts/extract-text-from-word-docx-simply/