如何用Python获取PDF多页目录(TOC)页码范围并优化识别逻辑?
问题说明
已实现PDF单页目录(TOC)起始页码的获取,但无法处理多页目录场景。当前通过硬编码正则匹配TABLE OF CONTENTS识别目录页,需优化识别方法,并实现多页目录起止页码的获取(如页码3至7)。
现有代码
目录页识别函数
def get_toc_page(page_text, pg_no): REG= "TABLE OF CONTENTS" if re.search(REG, page_text, re.IGNORECASE): search = re.search(REG, page_text, re.IGNORECASE) return REG, pg_no # else: # return 'not found',pg_no
主处理逻辑
filelist = glob.glob(path) for doc_path in tqdm(filelist): file_name = os.path.basename(doc_path) # 打开PDF doc = fitz.open(doc_path) #print(file_name, ' : ', len(doc)) # 文档总页数 i = -1 # 遍历页面 for page in doc: i +=1 if i == 10: # 仅检查前10页 break try: page.wrap_contents() page_text = page.get_text("text") if get_toc_page(page_text, i) != None: print(file_name, get_toc_page(page_text, i)) except Exception as e: print(e) print('处理出错:', file_name)
解决方案
一、优化目录页识别方法
- 扩展关键词匹配:覆盖中英文常见的目录表述,避免单一关键词的局限性
正则表达式改为:r"(TABLE OF CONTENTS|CONTENTS|目录|目錄)",忽略大小写匹配。 - 结合目录结构特征判断:目录页通常包含大量「标题+分隔符+页码」的格式(如
1.1 引言........5),通过匹配这类结构辅助验证,减少误判。
二、多页目录起止页码获取逻辑
- 标记起始页:识别到目录起始页后,记录起始页码。
- 向后遍历验证后续页面:对后续页面,检查是否仍存在目录结构特征;若连续多页无目录特征,或出现正文起始标识(如
第一章、Chapter 1),则标记为目录结束页。 - 设置合理的终止阈值:比如最多连续检查15页目录,避免无限遍历。
修改后的完整代码
import re import glob import os from tqdm import tqdm import fitz def is_toc_page(page_text): # 匹配常见的目录关键词 toc_keywords = r"(TABLE OF CONTENTS|CONTENTS|目录|目錄)" if re.search(toc_keywords, page_text, re.IGNORECASE): return True # 匹配目录特有的标题-页码结构(如 "章节名........123" 或 "章节名 123") toc_pattern = r".+[\. ]+\d+$" matches = re.findall(toc_pattern, page_text, re.MULTILINE) # 如果页面中这类结构超过3条,判定为目录页 if len(matches) >= 3: return True return False def get_toc_range(doc, max_check_pages=15): toc_start = None toc_end = None # 遍历前max_check_pages页查找目录 for pg_no in range(min(max_check_pages, len(doc))): page = doc[pg_no] page_text = page.get_text("text") if is_toc_page(page_text): if toc_start is None: toc_start = pg_no # 更新当前目录结束页 toc_end = pg_no else: # 如果已经识别过目录起始页,且当前页不是目录页,终止遍历 if toc_start is not None: break # 处理目录占满所有检查页的情况 if toc_start is not None and toc_end is None: toc_end = max_check_pages - 1 return (toc_start, toc_end) if toc_start is not None else None # 主逻辑 filelist = glob.glob(path) for doc_path in tqdm(filelist): file_name = os.path.basename(doc_path) try: doc = fitz.open(doc_path) toc_range = get_toc_range(doc) if toc_range: start, end = toc_range print(f"{file_name}: 目录页码范围 {start+1} - {end+1}") # 转换为人类习惯的页码(从1开始) else: print(f"{file_name}: 未找到目录") doc.close() except Exception as e: print(f"处理{file_name}出错: {str(e)}")
代码说明
is_toc_page函数:通过关键词+结构特征双重验证,判断页面是否为目录页,降低误判率。get_toc_range函数:遍历页面查找目录起始页,向后验证直到非目录页,返回目录的起止页码(PDF内部页码从0开始,输出时转换为从1开始)。- 主逻辑:遍历所有PDF文件,输出每个文件的目录页码范围。
内容的提问来源于stack exchange,提问作者Harshal Naik
相关产品推荐
相关产品推荐

