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

如何用Python高效识别PDF删除线文本并提取无删除线内容?

高效识别PDF中删除线文本的Python方案

为什么pdf2docx能识别删除线而PyMuPDF官方称无法直接支持?

PyMuPDF官方所说的“无法识别删除线文本”,指的是多数PDF并未将删除线作为文本的原生属性存储——大部分场景下,删除线是通过在文本上方绘制一条水平线条实现的,而非给文本标记删除线样式。pdf2docx之所以能识别,是因为它额外做了逻辑处理:提取PDF中的文本块与页面线条,通过计算两者的位置关系,判断文本是否被线条覆盖,进而标记为删除线格式。

更高效的直接解析方案(无需转docx)

跳过docx转换步骤,直接用PyMuPDF解析文本与线条,能大幅提升处理效率。核心逻辑:

  • 提取页面所有文本块及坐标
  • 提取页面中近似水平的线条(删除线通常为水平)
  • 通过位置匹配判断文本块是否被线条覆盖
  • 按需提取带删除线的文本,或反向提取无删除线的目标内容

代码示例

import os
import glob
import fitz  # PyMuPDF

def has_strikeout(text_block, lines):
    """判断文本块是否被删除线覆盖"""
    text_rect = fitz.Rect(text_block[:4])  # 文本块的矩形区域
    text_mid_y = (text_rect.y0 + text_rect.y1) / 2  # 文本块垂直中心位置
    # 遍历线条,检查是否有水平线条覆盖文本块中心区域
    for line in lines:
        line_rect = fitz.Rect(line[:4])
        # 匹配条件:水平方向覆盖文本块,垂直方向贴近文本中心
        if (line_rect.x0 < text_rect.x1 and line_rect.x1 > text_rect.x0 and
            abs(line_rect.y0 - text_mid_y) < 3 and abs(line_rect.y1 - text_mid_y) < 3):
            return True
    return False

def extract_target_text(pdf_path, get_strikeout=False):
    """提取PDF中目标文本:get_strikeout=True时提取带删除线的文本,否则提取无删除线的文本"""
    target_text = []
    doc = fitz.open(pdf_path)
    for page in doc:
        # 提取带坐标的文本块
        text_blocks = page.get_text("blocks")
        # 提取页面中近似水平的线条
        lines = []
        for path in page.get_drawings():
            for item in path["items"]:
                if item[0] == 'l':  # 'l'代表直线
                    x0, y0 = item[1]
                    x1, y1 = item[2]
                    if abs(y0 - y1) < 2:  # 筛选水平线条
                        lines.append((x0, y0, x1, y1))
        # 筛选目标文本
        for block in text_blocks:
            text = block[4].strip()
            if text and has_strikeout(block, lines) == get_strikeout:
                target_text.append(text)
    doc.close()
    return target_text

# 批量处理PDF文件
if __name__ == "__main__":
    pdf_files = glob.glob(os.getcwd() + r'\PDFs\*.pdf')
    all_target_text = []
    for pdf in pdf_files:
        print(f"处理文件: {pdf}")
        # 提取无删除线的目标文本,若要提取删除线文本则将get_strikeout设为True
        text = extract_target_text(pdf, get_strikeout=False)
        all_target_text.extend(text)
    print("所有无删除线的目标文本:")
    print("\n".join(all_target_text))

方案优势

  • 效率显著提升:直接解析PDF,避免docx转换的额外开销,处理10页PDF仅需数秒
  • 无中间文件:无需生成、删除临时docx文件,流程更简洁
  • 可定制性强:可根据实际PDF的删除线样式调整匹配阈值(如线条粗细、与文本的距离)

补充说明

少数规范生成的PDF会将删除线作为文本属性存储,这种情况可尝试用page.get_text("dict")查看文本的flags属性是否包含删除线标记,但此类场景占比极低,多数情况仍需通过线条匹配判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:35:36