【问题标题】:How to extract texts and tables pdfplumber如何提取文本和表格pdfplumber
【发布时间】:2022-07-20 01:49:31
【问题描述】:

使用 pdfplumber 库,您可以提取 PDF 页面的文本,也可以从 pdf 页面中提取表格。

问题是我似乎找不到提取文本表的方法。本质上,如果pdf以这种方式格式化:

text1
tablename
___________
| Header 1 |
------------
| row 1    |
------------

text 2

我希望输出是:

["text 1",
 "table name",
 [["header 1"], ["row 1"]],
 "text 2"]

在本例中,您可以从 pdfplumber 运行 extract_text:

with pdfplumber.open("example.pdf") as pdf:
    for page in pdf.pages:
        page.extract_text()

但这会将文本和表格提取为文本。您可以运行 extract_tables,但这只会为您提供表格。我需要一种同时提取文本和表格的方法。

这是以某种我不理解的方式内置到库中的吗?如果没有,这可能吗?

编辑:已回答

这直接来自已接受的答案,稍作调整即可修复它。非常感谢!

from operations import itemgetter

def check_bboxes(word, table_bbox):
    """
    Check whether word is inside a table bbox.
    """
    l = word['x0'], word['top'], word['x1'], word['bottom']
    r = table_bbox
    return l[0] > r[0] and l[1] > r[1] and l[2] < r[2] and l[3] < r[3]


tables = page.find_tables()
table_bboxes = [i.bbox for i in tables]
tables = [{'table': i.extract(), 'top': i.bbox[1]} for i in tables]
non_table_words = [word for word in page.extract_words() if not any(
    [check_bboxes(word, table_bbox) for table_bbox in table_bboxes])]
lines = []
for cluster in pdfplumber.utils.cluster_objects(
        non_table_words + tables, itemgetter('top'), tolerance=5):
    if 'text' in cluster[0]:
        lines.append(' '.join([i['text'] for i in cluster]))
    elif 'table' in cluster[0]:
        lines.append(cluster[0]['table'])

2022 年 7 月 19 日编辑:

更新了一个参数以包含 itemgetter,它现在是 pdfplumber 的 cluster_objects 函数所必需的(而不是字符串)

【问题讨论】:

  • 对于以后来这里的人来说,值得注意的是,这种方法只有在表格左右没有文字的情况下才有效。

标签: python pdf pdfplumber


【解决方案1】:

您可以获取表格的边界框,然后过滤掉其中的所有单词,如下所示:

def check_bboxes(word, table_bbox):
    """
    Check whether word is inside a table bbox.
    """
    l = word['x0'], word['top'], word['x1'], word['bottom']
    r = table_bbox
    return l[0] > r[0] and l[1] > r[1] and l[2] < r[2] and l[3] < r[3]


tables = page.find_tables()
table_bboxes = [i.bbox for i in tables]
tables = [{'table': i.extract(), 'doctop': i.bbox[1]} for i in tables]
non_table_words = [word for word in page.extract_words() if not any(
    [check_bboxes(word, table_bbox) for table_bbox in table_bboxes])]
lines = []
for cluster in pdfplumber.utils.cluster_objects(non_table_words+tables, 'doctop', tolerance=5):
    if 'text' in cluster[0]:
        lines.append(' '.join([i['text'] for i in cluster]))
    elif 'table' in cluster[0]:
        lines.append(cluster[0]['table'])

【讨论】:

  • 感谢您的回答,不幸的是,这不是我想要的。这只会删除表格上的所有单词,并且不会按顺序在同一列表中同时返回带有表格的文本行(如我的示例所示)
  • @JustinFuruness 更新了答案
  • 我刚试过,这个答案似乎把所有表格放在第一位,无论如何(而不是按照文本的顺序)。如果我能弄清楚如何让它们按顺序出现,我会接受答案。
  • 我想我明白了,这是因为您使用的是文本的 doctop 属性,但表格的顶部属性不匹配。我会用正确的答案更新我的问题,然后接受你的答案。非常感谢,这太棒了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多