PDF章节提取异常:正则提取到目录而非目标管理报告章节求助
解决默克年报合并管理报告提取错误(目录而非目标章节)的方案
问题根源
当前代码提取到目录而非目标章节,核心原因有三点:
- 起始正则匹配到了目录中的
Group Management Report条目,而非正文章节的标题 - 循环逻辑找到第一个结束标记就直接返回,未跳过目录里的
Consolidated Financial Statements链接 min_mdna_length的筛选逻辑未生效,因为提前返回了短内容的区间
具体改进方案
1. 优化正则,精准匹配正文章节标题
年报目录与正文的标题通常有格式差异,可利用分页符(\f,多数PDF转文本工具会生成)、页码或全大写格式来区分:
# 匹配带分页符的正文标题(适配多数转文本结果) item7_regex = re.compile(r"\fGroup\s+Management\s+Report\f", re.DOTALL) # 或匹配带页码的正文标题(比如正文标题前有14页的页码) item7_regex = re.compile(r"\n14\s+Group\s+Management\s+Report\n", re.DOTALL) # 或匹配全大写的正文标题(部分年报正文标题会全大写) item7_regex = re.compile(r"\nGROUP\s+MANAGEMENT\s+REPORT\n", re.DOTALL)
2. 调整提取逻辑,筛选符合长度要求的区间
修改代码,遍历所有可能的起始和结束位置,仅返回长度达标且位于正文区间的内容:
def extract_mdna(plain_text: str, min_mdna_length=25000): # 获取所有可能的起始匹配 start_matches = list(item7_regex.finditer(plain_text)) if not start_matches: return None for start_match in start_matches: start_pos = start_match.start() # 获取起始位置之后的所有结束匹配 end_matches = list(item8_regex.finditer(plain_text, start_pos + 1)) for end_match in end_matches: end_pos = end_match.start() content_len = end_pos - start_pos # 仅返回长度达标内容 if content_len >= min_mdna_length: return plain_text[start_pos:end_pos] return None
3. 利用页码精准锁定目标区间
目标章节位于第14-228页,可先通过页码定位文本范围,再在范围内提取章节:
def extract_mdna_by_page(plain_text: str): # 匹配第14页的起始位置 page14_match = re.search(r"\n14\s+", plain_text) if not page14_match: return None page_start = page14_match.start() # 匹配第229页的起始位置(作为章节结束的边界) page229_match = re.search(r"\n229\s+", plain_text, page_start) if not page229_match: return None page_end = page229_match.start() # 在页码区间内匹配章节标题 section_start = item7_regex.search(plain_text, page_start, page_end) section_end = item8_regex.search(plain_text, section_start.start() if section_start else page_start, page_end) if section_start and section_end: return plain_text[section_start.start():section_end.start()] return None
4. 验证转文本文件的格式差异
打开转后的文本文件,对比目录与正文的标题格式:
- 正文标题可能带有特殊标记(如换行、分页符、全大写)
- 目录条目通常带有后续页码(如
Group Management Report 14),可在正则中排除这种格式:# 排除目录中带页码的条目 item7_regex = re.compile(r"Group\s+Management\s+Report(?!\s+\d+)", re.DOTALL)
内容的提问来源于stack exchange,提问作者Limps
相关产品推荐
相关产品推荐

