pdfplumber 未拾取列并出现多行数据问题

问题描述 投票:0回答:1

所以我在我编写的 pdf 提取脚本中遇到了两件事。

首先,脚本没有选取最后一列“序列号” 我已经将我感兴趣的区域以及我需要的明确的垂直策略线框起来了boxed area and explicit vertical strategy lines

正如您从屏幕截图中看到的,垂直线整齐地划分了列,这在 pdf 的所有页面上都是如此。方框区域还捕获了所有页面上我想要的所有内容。

我的脚本在这里:

import pdfplumber

pdf_file = r"C:\Users\xxxx\Downloads\Active Aircraft Register.pdf"
box = (0, 35, 980, 565)
explicit_vertical_lines = [18, 57, 127, 325, 518, 713, 830, 920, 984]

all_tables = []


with pdfplumber.open(pdf_file) as pdf:
    for page in pdf.pages:
        cropped_page = page.crop(bbox=box)
        table = cropped_page.extract_table(table_settings={
            "vertical_strategy": "explicit",
            "explicit_vertical_lines": explicit_vertical_lines,
            "horizontal_strategy": "text",
        })
        if table:
            all_tables.extend(table)

# Check if we have any tables extracted
if not all_tables:
    print("No tables found in the PDF.")
else:
    for row in all_tables[:10]:
        print(row)

第二个问题是,一旦脚本完成提取,如果任何行中有一个多行单元格(例如地址或类型变体),它就会用空格单独放置每一行,有没有办法让它全部放在一个单元格上线?

我正在使用的 PDF 文件可以在此处下载来测试脚本:https://www.caacayman.com/wp-content/uploads/pdf/Active%20Aircraft%20Register.pdf

enter image description here

python pdf-scraping pdfplumber
1个回答
0
投票

pdf水管工0.11.4

使用水平策略

'text'
提取时,请务必记住
pdfplumber
会为每条检测到的线创建新的水平边缘。这些边缘从最左边字符的水平位置
x0
开始,到边界框内最右边字符的
x1
结束。如果定义的垂直边距这些新创建的水平边的端点太远,则在后续步骤中可能无法将它们检测为相交。这就是为什么您可能会丢失最右边的列 -
explicit_vertical_lines
中的最后一个垂直位置不与由字线构建的水平边缘相交。

为了解决这个问题,我们可以将 intersection_x_tolerance 参数增加到一个值来补偿水平边缘和垂直线之间的间隙,或者重新定义最右边垂直线的位置,使其与屏幕上的文本对齐。对了,像这样:

explicit_vertical_lines[-1] = max(c['x1'] for c in page.chars)

有关更多示例,您可以参考 此案例,它提供了更多详细信息,或者 这个顶部有丢失行的案例,它源于类似的问题。

但是,我想建议一种同时解决这两个问题的替代方法。由于源文档已被修改,原始链接不再相关,我将根据提供的屏幕截图进行解释。

如图所示,每个单元格中的数据与顶部垂直对齐,并且第一列中的每个单元格只有一行。因此,我们可以使用第一列中的单词来识别每个单元格的顶行。此方法涉及裁剪页面以隔离列、提取行/单词,并使用它们的

'top'
值作为
explicit_horizontal_lines
的点。这是我们可以使用的代码示例:

bbox = (0, 35, 980, 565)   # data bounding box 
first_col_bbox = [explicit_horizontal_lines[0], bbox[1],
                  explicit_horizontal_lines[1], bbox[3]]
words = page.crop(first_col_bbox).extract_words()
explicit_horizontal_lines = *(w['top'] for w in words), bbox[3]   # we neen bbox[3] at the end, 
                                                                  # which is the bottom of the data area,
                                                                  # to extract the row at the very bottom 
settings = {
    'horizontal_strategy': 'explicit',
    'vertical_strategy': 'explicit',
    'explicit_vertical_lines': explicit_vertical_lines,
    'explicit_horizontal_lines': explicit_horizontal_lines,
}
table = page.crop(bbox).extract_table(settings)
© www.soinside.com 2019 - 2024. All rights reserved.