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

如何检测PDF提取文本的段落?能否通过位置区分文本块?

利用文本块位置区分段落的实现方法

核心思路

PyMuPDF提取的每个文本块(TextBlock)都自带位置信息(bbox边界框),可以通过对比相邻文本块的垂直间距、水平对齐、行高这些维度,精准区分同段落换行和独立文本块,进而划分段落。

具体实现步骤

  • 提取文本块及位置数据:用PyMuPDF遍历PDF页面,获取每个文本块的bbox(含左上角x0,y0、右下角x1,y1坐标)和文本内容。注意PyMuPDF的坐标原点在页面左下角,y值越大位置越靠上。
  • 计算垂直间距判定段落:计算当前块底部y0与下一块顶部y1的差值(因y轴向上,差值为上块y0 - 当前块y1)。若这个间距大于行高的1.5-2倍,则判定为新段落;若间距接近行高,则属于同段落的换行。
  • 结合水平对齐辅助判断:如果相邻文本块的左对齐位置(x0)差异极小(比如小于5个单位),且垂直间距符合换行阈值,基本可判定为同段落换行;若左对齐偏移明显,即使间距小,也可能是新段落或列表项。
  • 处理特殊排版:
    • 列表项:通常有固定缩进或开头符号(如•、数字),可结合文本开头特征和位置偏移判断。
    • 标题:字号、行高通常更大,垂直间距会远大于普通段落,可单独识别。

示例代码

import fitz

def split_into_paragraphs(page):
    # 获取所有文本块,格式为(x0, y0, x1, y1, text, block_no, type)
    blocks = page.get_text("blocks")
    # 按y坐标从大到小排序(页面顶部内容y值更大)
    blocks.sort(key=lambda b: -b[1])
    paragraphs = []
    current_para = []
    base_line_height = None

    for idx, block in enumerate(blocks):
        x0, y0, x1, y1, text, _, _ = block
        current_line_h = y1 - y0
        # 初始化基准行高
        if base_line_height is None:
            base_line_height = current_line_h

        if idx == 0:
            current_para.append(text.strip())
            continue

        # 获取上一个文本块的位置
        prev_block = blocks[idx-1]
        prev_y0 = prev_block[1]
        # 计算两个文本块的垂直间距
        vertical_gap = prev_y0 - y1

        # 判定新段落的条件:间距超过行高1.8倍,或左对齐偏移过大
        if vertical_gap > base_line_height * 1.8 or abs(x0 - prev_block[0]) > 10:
            paragraphs.append("\n".join(current_para))
            current_para = [text.strip()]
            base_line_height = current_line_h
        else:
            current_para.append(text.strip())

    # 添加最后一个段落
    if current_para:
        paragraphs.append("\n".join(current_para))
    
    return paragraphs

# 调用示例
doc = fitz.open("target.pdf")
target_page = doc[0]
result_paragraphs = split_into_paragraphs(target_page)
for para in result_paragraphs:
    print(para)
    print("---段落分割线---")

注意事项

  • 不同PDF排版差异大,阈值(如1.8倍行高、10单位偏移)需根据实际文档调整。
  • 多列排版的PDF,需先判断文本块所属列,再按列分别处理段落。
  • 若文本块内部包含多行,可先拆分单行后再进行位置对比。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:27:57