如何仅用Python标准库实现.doc文件指定关键词搜索?
针对.doc文件的轻量关键词搜索方案(仅用Python标准库)
核心思路
.doc属于OLE复合文档格式,无法像docx那样通过解压读取XML内容。我们可以直接解析二进制结构,提取其中的WordDocument核心流,过滤出可识别的文本片段后匹配关键词,全程依赖Python标准库实现。
实现代码
import os import re import struct import logger def doc_file(root: str, file: str, keywords: list) -> list: hits = [] file_path = os.path.join(root, file) try: with open(file_path, 'rb') as f: # 验证是否为合法OLE复合文档 header = f.read(8) if header != b'\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1': logger.warning(f"{file} is not a valid .doc file") return hits # 读取目录条目数量,定位目录区 f.seek(0x30) dir_entry_count = struct.unpack('<I', f.read(4))[0] f.seek(0x40) # 遍历目录条目,找到WordDocument流 word_stream_info = None for _ in range(dir_entry_count): entry = f.read(128) name = entry[:64].decode('utf-16le').rstrip('\x00') stream_size = struct.unpack('<Q', entry[0x70:0x78])[0] stream_start_sec = struct.unpack('<I', entry[0x78:0x7C])[0] if name == 'WordDocument': word_stream_info = (stream_size, stream_start_sec) break if not word_stream_info: logger.warning(f"No WordDocument stream found in {file}") return hits # 获取扇区大小,定位到流起始位置 f.seek(0x18) sector_size = 1 << struct.unpack('<H', f.read(2))[0] f.seek(sector_size * word_stream_info[1]) stream_data = f.read(word_stream_info[0]) # 过滤出可打印文本(剔除控制字符和非ASCII乱码) text = ''.join([chr(b) for b in stream_data if 32 <= b <= 126 or b in [9, 10, 13]]) # 匹配关键词 for keyword in keywords: if re.search(keyword, text): hits.append(keyword) except Exception as e: logger.warning(f"Failed to process {file}: {str(e)}") return hits return hits
说明
- 直接操作二进制文件解析OLE结构,仅提取核心的文本承载流,避免复杂格式解析
- 通过过滤非打印字符,保留可识别的文本片段用于关键词匹配
- 完全依赖Python标准库,无需额外安装第三方包
- 局限性:无法还原所有格式化文本,可能遗漏部分隐藏内容,但满足基础关键词搜索需求
内容的提问来源于stack exchange,提问作者Bemofresh
相关产品推荐
相关产品推荐

