仅使用标准Python库在.doc文件中搜索特定单词



我正在构建一个程序,通过许多不同的文件格式寻找指定的关键字搜索,我有一些问题,找到有关如何读取。doc文件的信息。我能够让.docx文件在函数中使用以下内容:

def docx_file(root: str, file: str, keywords: list) -> list:
hits = []
keywords = keywords.copy()
try:
document = zipfile.ZipFile(os.path.join(root,file))
docXml = xml.dom.minidom.parseString(document.read('word/document.xml')).toprettyxml()
for keyword in keywords:
if bool(re.search(keyword, docXml)):
hits.append(keyword)
except:
logger.warning(f"failed to open {root}\{file}")
return []
return hits

不幸的是,.doc文件不能以同样的方式工作。我正在寻找一个轻量级的解决方案,并且真的不希望为这个功能导入额外的库。

事先感谢您的帮助。

我查看了下面的输出:

document = zipfile.ZipFile(os.path.join(root,file))
document.filelist

我然后跑了:

for doc in document.filelist:
docXml = xml.dom.minidom.parseString(document.read(doc.filename)).toprettyxml(indent="   ")
print(docXml)

根据输出,我认为。docx解决方案不适用于。doc文件。

编辑:此外,我目前正在研究如何使用。

的输出。
document = open(os.path.join(root,file), 'rb')
for line in document.readlines():
print(line)

我已经尝试解码输出,它只是给出:

☻☺àùOh«
+'³Ù0l☺◄☺↑Microsoft Office Word@@€ћs¶юШ☺@€ћs¶юШ☺♥☻♥♥.♥юя

为我目前为止尝试过的任何编码。

.docx是XML-in-a-Zip格式,很容易阅读,而.doc文件(不含X)是二进制格式,很难解析,特别是没有第三方库的情况下。

您可以为这种文件格式实现部分解析器(基于@micromoses链接的规范),但这可能很繁琐。

另一个解决方案,更快,但也不太可靠,是只grep文件。我刚刚测试了一下:在一个文件中明文写我自己的名字,保存为.doc,我可以grep它。这是因为该单词在文件格式中可能是按字节对齐的,因此可以进行匹配。

下面是一个快速演示:

from pathlib import Path
filepath = Path("/home/stack_overflow/parse_me.doc")
word = "Pinjon"
with open(filepath, "rb") as doc_file:
binary_data = doc_file.read()
if word.encode("utf-16-le") in binary_data:
print("word found (LE)")
elif word.encode("utf-16-be") in binary_data:
print("word found (BE)")
else:
print("word not found")
word found (LE)

我的电脑是Little Endian,但我涵盖了两种情况(LE/BE)。

我相信我找到了一个适合我的问题的解决方案,这是一个由Viktor写的代码片段的轻微变化。

special_chars = {
"b'\t'": 't',
"b'\r'": 'n',
"b'\x07'": '|',
"b'\xc4'": 'Ä',
"b'\xe4'": 'ä',
"b'\xdc'": 'Ü',
"b'\xfc'": 'ü',
"b'\xd6'": 'Ö',
"b'\xf6'": 'ö',
"b'\xdf'": 'ß',
"b'\xa7'": '§',
"b'\xb0'": '°',
"b'\x82'": '‚',
"b'\x84'": '„',
"b'\x91'": '‘',
"b'\x93'": '“',
"b'\x96'": '-',
"b'\xb4'": '´'
}
def doc_strings(path: Path) -> str:
output_string = ''
with open(path, 'rb') as stream:
stream.seek(2560)
current_stream = stream.read(1)
while not (str(current_stream) == "b'\xfa'"):
if str(current_stream) in special_chars.keys():
output_string += special_chars[str(current_stream)]
else:
try:
char = current_stream.decode('UTF-8')
if char.isalnum() or char == ' ':
output_string += char
except UnicodeDecodeError:
output_string += ''
current_stream = stream.read(1)
return output_string

最新更新