You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 并行处理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)
  1. 修复原代码的逻辑bug:你原代码中key_termx = x[0]会导致不管匹配到哪个关键词,都只记录第一个,优化后的代码会记录所有实际匹配到的关键词。
  2. 提前终止提取:不需要提取完整PDF文本,每提取一页就检查关键词,匹配到就停止处理该PDF,大幅节省时间。
  3. 资源自动释放:用with语句或显式关闭PDF对象,避免资源泄漏。

四、额外排查点

  • 在Acrobat中打开乱码页面的PDF,右键→文档属性→字体,查看字体是否为“嵌入”状态——如果是“未嵌入”,就是字体缺失导致的乱码,换用PyMuPDF或pdfplumber即可解决。
  • 若为OCR后的PDF,检查OCR工具是否将识别文本正确写入了PDF的文本层(可以用Acrobat的“选择工具”选中关键词,确认文本是可选中的状态)。

内容的提问来源于stack exchange,提问作者J. Dykstra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:09:47