使用PyMuPDF提取PDF高亮内容转DataFrame的去重及格式问题
解决方案
问题根因拆解
- 重复条目问题:大概率是PyMuPDF读取高亮标注时,同一个高亮区域被多次识别(比如跨页高亮、高亮标注存在重叠/重复锚点),你之前用单词语义去重的逻辑不对,应该基于高亮区域的坐标和内容哈希去重,而不是基于内容本身去重。
- 空格拆分字段问题:本质是没有先做表格结构对齐就直接全局替换空格,应该先识别表格的列分隔边界,再做字段提取,不要全局替换空格。
具体实现代码(基于PyMuPDF)
import fitz # PyMuPDF import pandas as pd from hashlib import md5 def extract_highlighted_table(pdf_path): doc = fitz.open(pdf_path) highlight_items = [] for page in doc: # 提取页面所有高亮标注 for annot in page.annots(): if annot.type[0] == 8: # 8对应高亮标注类型 # 获取高亮区域的坐标范围 rect = annot.rect # 提取该矩形区域内的所有文字,保留原始空格,不做提前替换 text = page.get_text("text", clip=rect).strip() if not text: continue # 生成区域唯一哈希:用页码+坐标+内容前100字做哈希,避免重复识别同一个高亮 hash_key = md5(f"{page.number}_{rect.x0}_{rect.y0}_{rect.x1}_{rect.y1}_{text[:100]}".encode()).hexdigest() highlight_items.append({ "hash_key": hash_key, "page": page.number, "y0": rect.y0, # 用y坐标做行排序,x坐标做列排序 "x0": rect.x0, "text": text }) # 第一步:基于哈希去重,完全避免重复条目 df_raw = pd.DataFrame(highlight_items).drop_duplicates(subset="hash_key", keep="first") # 第二步:按行、列排序,还原表格结构 # 先按y坐标聚类,同一行的y坐标差值小于10(可根据PDF实际排版调整阈值) df_raw["row_id"] = (df_raw["y0"].diff().abs() > 10).cumsum() # 同一行内按x坐标排序,确定列顺序 df_raw = df_raw.sort_values(["row_id", "x0"]).reset_index(drop=True) # 第三步:生成name|value结构的DataFrame,假设表格第一列为name,第二列为value,可自行调整列索引 result = [] for row_id, group in df_raw.groupby("row_id"): cols = group["text"].tolist() if len(cols) >=2: result.append({"name": cols[0], "value": cols[1]}) return pd.DataFrame(result) # 调用示例 df = extract_highlighted_table("你的文件路径.pdf") print(df)
关键优化点说明
- 去重逻辑:不再基于内容本身去重,转而基于高亮标注的物理位置+内容哈希判断重复,既可以解决同一个高亮被多次识别的问题,也不会误删不同位置出现的相同有效内容(比如不同行都出现的LTD)
- 字段拆分逻辑:取消全局空格替换的操作,通过坐标聚类还原表格的行列结构,直接提取完整的单元格内容,天然保留带空格的完整字段(比如Apple Inc不会被拆分)
适配调整提示
如果你的表格列数不是2列,或者排版偏差较大,可以调整两个参数:
- 行聚类阈值:
diff().abs() > 10里的10,数值越大越容易把相邻行合并为同一行 - 列提取规则:如果name|value不在前两列,可以修改
cols[0]、cols[1]的索引
内容的提问来源于stack exchange,提问作者technophile_3
相关产品推荐
相关产品推荐

