如何用Python正则匹配PDF中带空格分隔的目标词汇?
解决PDF文本中带多余空格的词汇正则匹配问题
核心解决方案
针对PDF读取时词汇被插入多余空格的问题,我们可以将目标关键词转换为允许字符间存在任意空白字符的正则表达式,这样不管词汇内部有没有被错误插入空格,都能匹配成功。
具体实现时,写一个辅助函数来处理关键词:
def build_whitespace_insensitive_pattern(keyword): # 转义关键词中的正则特殊字符,然后在每个字符后添加允许任意空白的规则 escaped = re.escape(keyword) # 把关键词拆成单个字符,每个字符后加\s*,最后拼接 return ''.join([char + r'\s*' for char in escaped])
比如输入"Extremalproblem",会生成正则模式:E\s*x\s*t\s*r\s*e\s*m\s*a\s*l\s*p\s*r\s*o\s*b\s*l\s*e\s*m,这个模式能匹配Extremalproblem、Extre malproblem、E x t r e m a l p r o b l e m等任意带内部空格的变体。
优化后的完整代码
同时修复原代码中遍历列表时修改原列表、重复提取文本等问题:
import PyPDF2 import re import os def build_whitespace_insensitive_pattern(keyword): escaped = re.escape(keyword) return ''.join([char + r'\s*' for char in escaped]) # 定义关键词组,每组只要匹配到一个就算完成该组 keyword_groups = [ ['Grosses Einmaleins', 'Einmaleins'], ['Extremwertprobleme', 'Extremalprobleme', 'Extremwerte', 'Optimierung', 'Optimierungsprobleme'] ] # 预编译所有关键词的正则模式,提升匹配效率 compiled_patterns = [] for group in keyword_groups: group_patterns = [] for keyword in group: pattern = build_whitespace_insensitive_pattern(keyword) # 用re.IGNORECASE编译,忽略大小写 compiled = re.compile(pattern, re.IGNORECASE) group_patterns.append(compiled) compiled_patterns.append(group_patterns) # 遍历当前目录下的所有子目录 for root, dirs, files in os.walk(".", topdown=True): for dir_name in dirs: dir_path = os.path.join(root, dir_name) # 获取目录下的所有PDF文件(可根据需要过滤后缀) pdf_files = [f for f in os.listdir(dir_path) if f.lower().endswith('.pdf')] for pdf_file in pdf_files: pdf_path = os.path.join(dir_path, pdf_file) reader = PyPDF2.PdfReader(pdf_path) # 标记哪些组已经匹配到 matched_groups = [False] * len(compiled_patterns) matched_count = 0 # 遍历每页文本 for page in reader.pages: text = page.extract_text() if not text: continue # 跳过无文本的页面 # 检查未匹配的组 for idx, group_patterns in enumerate(compiled_patterns): if matched_groups[idx]: continue # 该组已匹配,跳过 for pattern in group_patterns: if pattern.search(text): matched_groups[idx] = True matched_count += 1 break # 该组匹配到一个关键词就停止检查 # 如果所有组都匹配到了,提前退出循环 if matched_count == len(compiled_patterns): break # 输出结果 print(f"{pdf_file}: {matched_count / len(compiled_patterns)}")
关键优化点说明
- 预编译正则表达式:避免每次匹配时重复编译,提升处理大量PDF时的效率。
- 标记已匹配组:不再修改原关键词列表,而是用布尔数组标记已匹配的组,避免迭代时的列表混乱问题。
- 单页文本只提取一次:每个页面的文本只提取一次,减少不必要的IO操作。
- 提前终止循环:当所有关键词组都匹配到后,直接停止遍历剩余页面,节省时间。
- 过滤PDF文件:只处理后缀为pdf的文件,避免非PDF文件干扰。
内容的提问来源于stack exchange,提问作者ghxk
相关产品推荐
相关产品推荐

