如何基于NLP与PyPDF2提取PDF关键词、标题、表名及对应页码
PDF定向内容提取实现方案
原有代码的核心缺陷
- 跨页拼接全量文本,丢失内容与对应页码的映射关系
- 未针对目标提取内容设置专属匹配规则,无法区分全大写章节标题、表名与普通文本
- 扫描件识别逻辑粗糙,仅在全文档提取为空时触发OCR,单页扫描的场景下识别失效
实施前置准备
提前安装所需依赖库,执行命令:pip install pypdf2 textract nltk
首次运行需下载NLTK基础语料,执行:
import nltk nltk.download('punkt') nltk.download('stopwords')
提取规则设计
针对三类目标内容设置独立的匹配逻辑,降低误判率:
- 全大写粗体章节标题:匹配独立成行、全大写、字符长度在2-50区间的文本,排除正文内夹杂的短全大写缩写、普通句子;针对原生PDF可补充字体元数据校验,确认文本块为粗体格式(字体名称包含
Bold标识) - 表名:匹配独立成行、以
Table + 连续数字为开头的文本,完整保留表名后的括号注释内容 - 通用关键词:沿用原有分词、过滤停用词、过滤标点的处理逻辑,逐页提取关键词并绑定对应页码,不做跨页合并
逐页处理流程
所有页面按统一流程处理:
- 逐页通过PyPDF2提取原生文本
- 若单页提取文本长度不足10字符,判定为扫描页,单独调用textract对当前页做OCR识别,避免全文档OCR带来的页码错位问题
- 按行拆分当前页文本,逐行匹配章节标题、表名规则,命中即记录内容与对应页码
- 对当前页全量文本做分词清洗,提取通用关键词并绑定页码
完整可运行代码
import re import PyPDF2 import textract from nltk.tokenize import word_tokenize from nltk.corpus import stopwords # 定义匹配规则 section_pattern = re.compile(r'^[A-Z][A-Z\s&\-]{2,50}$') table_pattern = re.compile(r'^Table\s+\d+.*$') punctuations = ['(',')',';',':','[',']',',','^','=','-','!','.','{','}','/','#','&'] stop_words = stopwords.words('english') def main(pdf_path="Test1.pdf", output_path="extracted_results.txt"): results = [] # 打开PDF文件 with open(pdf_path, "rb") as f: pdf_reader = PyPDF2.PdfReader(f) total_pages = len(pdf_reader.pages) # 逐页处理 for page_idx in range(total_pages): # 转换为实际页码(PyPDF2索引从0开始) actual_page_num = page_idx + 1 current_page = pdf_reader.pages[page_idx] page_text = current_page.extract_text() # 单页识别失败时触发OCR if len(page_text.strip()) < 10: page_text = textract.process( pdf_path, method='tesseract', language='eng', pages=actual_page_num ).decode('utf-8') # 逐行匹配章节标题、表名 for line in page_text.split('\n'): line_content = line.strip() if not line_content: continue # 匹配全大写章节标题 if section_pattern.match(line_content): results.append(f"{line_content} in Page {actual_page_num}") # 匹配表名 if table_pattern.match(line_content): results.append(f"{line_content} in Page {actual_page_num}") # 提取当前页通用关键词 tokens = word_tokenize(page_text) page_keywords = [ word for word in tokens if word.lower() not in stop_words and word not in punctuations and len(word.strip()) > 1 ] for keyword in page_keywords: results.append(f"Keyword: {keyword} in Page {actual_page_num}") # 结果写入本地文件 with open(output_path, "w", encoding="utf-8") as output_f: output_f.write('\n'.join(results)) print(f"提取完成,结果已保存至{output_path}") if __name__ == "__main__": main()
适配调整说明
- 若不需要输出通用关键词,仅保留章节标题、表名的提取结果,可注释掉代码中关键词收集的逻辑块
- 若出现章节标题误判,可收窄匹配规则的长度范围,比如要求匹配的全大写文本至少包含3个单词,过滤短文本缩写
- 针对原生PDF的粗体校验需求,可在逐行匹配阶段补充文本块的字体属性判断,仅当字体标识包含粗体属性时才判定为有效章节标题
内容的提问来源于stack exchange,提问作者Sweety
相关产品推荐
相关产品推荐

