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

使用PyPDF2+re定位PDF页码时重复匹配导致tabula提表错误

问题根因

出现该问题有三个核心原因:

  • 子串误匹配:短目标串STATEMENT OF PROFIT AND LOSS是长目标串CONSOLIDATED STATEMENT OF PROFIT AND LOSS的子串,遍历到第131页时,长串内容会触发短串的匹配规则
  • 变量无保护:匹配到对应页码后没有终止对应项的匹配逻辑,第131页的误匹配会覆盖第73页已经存入sat变量的正确值
  • 逻辑错误:原代码打印S对应页码时错误使用了i+1,和标注的S实际在131页的位置不符
修复方法

按以下逻辑调整代码即可:

  • 初始化变量时增加命中标记,两个目标串只要找到对应页码,就不再更新对应存储变量,防止值被覆盖
  • 调整匹配顺序,优先匹配长度更长的目标串S,当前页命中S后直接跳过P的匹配判断,从逻辑上避免子串误触发
  • 两个目标都命中后直接终止PDF遍历,不需要扫描剩余页面,提升运行效率
  • 提取表格时分别输出两个页面对应的文件,避免结果覆盖
修复后完整代码
import tabula
import PyPDF2
import re

pdffile = "NCC.pdf"
reader = PyPDF2.PdfFileReader(pdffile)

P = "STATEMENT OF PROFIT AND LOSS"   # 实际位于PDF第73页
S = "CONSOLIDATED STATEMENT OF PROFIT AND LOSS"   # 实际位于PDF第131页

# 初始化页码存储变量和命中标记
sat = None
con = None
found_p = False
found_s = False

for i, page in enumerate(reader.pages, start=1):
    # 两个目标都找到就终止遍历
    if found_p and found_s:
        break
    text = page.extract_text()
    # 优先匹配更长的目标串S
    if not found_s and re.search(re.escape(S), text):
        print(f"S String Found on Page: {i}")
        con = str(i)
        found_s = True
        # 命中长串后跳过当前页P的匹配,避免子串误判
        continue
    # 仅在未找到P时执行匹配
    if not found_p and re.search(re.escape(P), text):
        print(f"P String Found on Page: {i}")
        sat = str(i)
        found_p = True

# 校验页码存在后再执行提取,避免空值报错
if sat:
    tabula.convert_into(pdffile, "profit_loss.csv", output_format="csv", pages=sat)
if con:
    tabula.convert_into(pdffile, "consolidated_profit_loss.csv", output_format="csv", pages=con)

补充:如果PDF其他位置还存在零散的子串误匹配,可以给匹配规则增加边界限制,比如将P的匹配条件改为re.search(rf"(?<!\S){re.escape(P)}(?!\S)", text),保证匹配到的目标串前后是空白字符或行首行尾,进一步提升匹配准确率。

内容的提问来源于stack exchange,提问作者Shashi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:15:45