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

使用pdfplumber提取PDF文本时如何判断页面是否存在多栏布局

多栏PDF动态识别与文本提取解决方案

预处理:过滤页眉页脚等无关元素

基于pdfplumber的字符级坐标能力做初步过滤:

  • 调用page.chars获取页面所有字符的x0(左边界)、x1(右边界)、top(上边界)、bottom(下边界)、size(字号)属性
  • 按垂直分布过滤页眉页脚:默认剔除页面上下各5%高度范围内的字符,也可结合页码、固定抬头等特征做精准匹配,仅保留正文区域字符用于后续判断

动态栏数识别逻辑

核心利用栏间空白远大于普通字间距的特征判断:

  • 统计正文字符的平均字号,将正文字号的2倍设为栏间空白的最小阈值(可根据PDF类型微调,学术文献可设为3倍)
  • 生成水平方向的字符覆盖密度:将页面水平方向按1px粒度拆分,统计每个x坐标点是否有字符覆盖
  • 提取连续空白区间:长度达到阈值的连续空白即为栏间分隔带,分隔带的数量+1就是页面的实际栏数
  • 异常修正:如果识别到的各栏宽度差超过30%,说明存在跨栏标题、浮动图片等元素,可先剔除大字号跨栏元素后重新做识别

分栏文本提取实现

识别栏数后按以下逻辑提取避免跨栏拼接:

  • 取所有栏间分隔带的中点作为拆分坐标,将正文区域切分为对应数量的独立垂直栏块
  • 调用page.crop(bbox)方法裁剪出单个栏块的区域,按默认的从上到下顺序提取单栏文本
  • 按从左到右的顺序拼接所有栏的提取结果,再做跨行合并、指定短语匹配即可

简化实现代码

import pdfplumber

def extract_dynamic_layout_text(page, edge_cut_ratio=0.05, gap_factor=2):
    # 提取所有字符并过滤页眉页脚
    all_chars = page.chars
    page_h = page.height
    valid_min_y = page_h * edge_cut_ratio
    valid_max_y = page_h * (1 - edge_cut_ratio)
    valid_chars = [c for c in all_chars if valid_min_y < c["top"] < valid_max_y]
    if not valid_chars:
        return ""
    
    # 计算栏间空白阈值
    avg_font_size = sum(c["size"] for c in valid_chars) / len(valid_chars)
    min_gap_width = avg_font_size * gap_factor
    
    # 统计水平覆盖情况
    min_x = min(c["x0"] for c in valid_chars)
    max_x = max(c["x1"] for c in valid_chars)
    x_cover = [False] * (int(max_x) + 2)
    for c in valid_chars:
        for x in range(int(c["x0"]), int(c["x1"]) + 1):
            x_cover[x] = True
    
    # 识别栏间分隔点
    split_points = [min_x]
    current_gap = 0
    for x in range(int(min_x), int(max_x) + 1):
        if not x_cover[x]:
            current_gap += 1
        else:
            if current_gap >= min_gap_width:
                split_points.append(x - current_gap / 2)
            current_gap = 0
    split_points.append(max_x)
    
    # 分栏提取文本并拼接
    full_text = []
    for i in range(len(split_points) - 1):
        col_bbox = (split_points[i], valid_min_y, split_points[i+1], valid_max_y)
        col_text = page.crop(col_bbox).extract_text()
        if col_text:
            full_text.append(col_text)
    return "\n".join(full_text)

注意事项

  • 处理包含大量图片的PDF时,可先过滤掉图片区域的坐标再做栏数识别,避免干扰
  • 阈值参数可根据目标PDF的共性特征调整,比如政府公文多为单栏、学术期刊多为2-3栏,可针对性优化阈值减少误判

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:36:04