Python读取OCR PDF出现乱码致关键词搜索遗漏问题求助
问题分析与优化建议
一、PDF部分页面乱码漏检的原因
你遇到的部分页面提取乱码、关键词漏检问题,主要是以下几种情况导致的:
- 字体嵌入缺失:有些PDF在Acrobat中能正常显示,是因为Acrobat会自动调用系统字体做 fallback 补充,但实际PDF文件并没有嵌入对应的字体。PyPDF2没有这种自动补全机制,提取文本时无法正确映射字符,就会出现类似“藛藴”的乱码。
- 非标准PDF结构:即使设置了
strict=False,一些采用非常规压缩、弱加密或自定义布局的PDF,PyPDF2的文本提取逻辑还是会失效,导致部分页面提取异常。 - OCR文本层异常:虽然你提到已经做了OCR,但要排查乱码页面的OCR是否真正把识别后的文本正确写入了PDF的文本层——如果只是在扫描图像上叠加了文本,但文本层编码存在问题,也会导致提取乱码。
二、解决乱码问题的替代方案
PyPDF2的文本提取能力相对有限,推荐换用兼容性更强的库:
方案1:使用PyMuPDF(fitz)
它对各种PDF格式的兼容性极强,提取速度快,文本准确率远高于PyPDF2,甚至支持提取带密码的加密PDF。示例代码片段:
import fitz def extract_pdf_text(file_path): doc = fitz.open(file_path) text = "" for page in doc: page_text = page.get_text() if page_text: # 跳过空页避免无效拼接 text += page_text doc.close() return text
方案2:使用pdfplumber
它对复杂布局的PDF支持更好,能保留文本位置信息,对字体缺失的情况处理也更友好:
import pdfplumber def extract_pdf_text(file_path): text = "" with pdfplumber.open(file_path) as pdf: for page in pdf.pages: page_text = page.extract_text() if page_text: text += page_text return text
三、代码提速与优化建议
你的当前代码有不少可以优化的点,既能提升速度,也能修复逻辑bug:
- 并行处理PDF:遍历大量PDF时,单线程效率极低,用
ProcessPoolExecutor做多进程并行处理(PDF提取是CPU密集型任务,多进程比多线程更高效):
from concurrent.futures import ProcessPoolExecutor import os import re import fitz # 预编译正则表达式,提升匹配速度 key_pattern = re.compile('|'.join(['Search term 1', 'Search term 2', 'Search term 3']), re.IGNORECASE) def process_single_pdf(file_path): try: doc = fitz.open(file_path) # 提前终止:每提取一页就检查关键词,匹配到就停止提取 for page in doc: page_text = page.get_text() if key_pattern.search(page_text): # 提取需要的信息 dirpath = os.path.dirname(file_path) rulex = dirpath.split("Rule")[1] matched_terms = [term for term in ['Search term 1', 'Search term 2', 'Search term 3'] if re.search(term, page_text, re.IGNORECASE)] doc.close() return (rulex, os.path.basename(file_path), ', '.join(matched_terms)) doc.close() return None except Exception as e: print(f"处理文件{file_path}出错: {str(e)}") return None # 收集所有PDF路径 pdf_location = r'PDF Directory' pdf_paths = [] for dirpath, _, filenames in os.walk(pdf_location): for filename in filenames: if filename.endswith('.pdf'): pdf_paths.append(os.path.join(dirpath, filename)) # 并行处理 results = [] with ProcessPoolExecutor(max_workers=os.cpu_count()) as executor: futures = [executor.submit(process_single_pdf, path) for path in pdf_paths] for future in futures: res = future.result() if res: results.append(res) # 写入CSV import csv with open('pdf_search_results.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['Rule', 'Filename', 'Matched Key Terms']) writer.writerows(results)
- 修复原代码的逻辑bug:你原代码中
key_termx = x[0]会导致不管匹配到哪个关键词,都只记录第一个,优化后的代码会记录所有实际匹配到的关键词。 - 提前终止提取:不需要提取完整PDF文本,每提取一页就检查关键词,匹配到就停止处理该PDF,大幅节省时间。
- 资源自动释放:用
with语句或显式关闭PDF对象,避免资源泄漏。
四、额外排查点
- 在Acrobat中打开乱码页面的PDF,右键→文档属性→字体,查看字体是否为“嵌入”状态——如果是“未嵌入”,就是字体缺失导致的乱码,换用PyMuPDF或pdfplumber即可解决。
- 若为OCR后的PDF,检查OCR工具是否将识别文本正确写入了PDF的文本层(可以用Acrobat的“选择工具”选中关键词,确认文本是可选中的状态)。
内容的提问来源于stack exchange,提问作者J. Dykstra
相关产品推荐
相关产品推荐

