Python 使用 Camelot 解析 PDF 并提取 Table 标题

Python PDF Parsing with Camelot and Extract the Table Title

Camelot 是一个很棒的 Python 库,可以从 pdf 文件中提取 table 作为数据框。但是,我正在寻找一种解决方案,该解决方案还 returns 写在 table 正上方的 table 描述文本。

我用于从 pdf 中提取 tables 的代码是这样的:

import camelot
tables = camelot.read_pdf('test.pdf', pages='all',lattice=True, suppress_stdout = True)

我想提取 table 上方的文字,即 THE PARTICULARS,如下图所示。

对我来说最好的方法是什么?感谢任何帮助。谢谢

您可以直接创建 Lattice 解析器

            parser = Lattice(**kwargs)
            for p in pages:
                t = parser.extract_tables(p, suppress_stdout=suppress_stdout,
                                          layout_kwargs=layout_kwargs)
                tables.extend(t)

然后您可以访问包含页面中所有组件的 parser.layout。这些组件都有 bbox (x0, y0, x1, y1) 并且提取的 table 也有一个 bbox 对象。您可以在其顶部找到最接近 table 的组件并提取文本。

这是我搞笑的糟糕实现,只是为了让人们可以大笑并受到启发去做更好的实现并为伟大的 camelot 包做出贡献:)

注意事项:

  • 仅适用于非旋转表
  • 这是一个启发式
  • 代码有问题
# Helper methods for _bbox
def top_mid(bbox):
    return ((bbox[0]+bbox[2])/2, bbox[3])

def bottom_mid(bbox):
    return ((bbox[0]+bbox[2])/2, bbox[1])

def distance(p1, p2):
    return math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)

def get_closest_text(table, htext_objs):
    min_distance = 999  # Cause 9's are big :)
    best_guess = None
    table_mid = top_mid(table._bbox)  # Middle of the TOP of the table
    for obj in htext_objs:
        text_mid = bottom_mid(obj.bbox)  # Middle of the BOTTOM of the text
        d = distance(text_mid, table_mid)
        if d < min_distance:
            best_guess = obj.get_text().strip()
            min_distance = d
    return best_guess

def get_tables_and_titles(pdf_filename):
    """Here's my hacky code for grabbing tables and guessing at their titles"""
    my_handler = PDFHandler(pdf_filename)  # from camelot.handlers import PDFHandler
    tables = camelot.read_pdf(pdf_filename, pages='2,3,4')
    print('Extracting {:d} tables...'.format(tables.n))
    titles = []
    with camelot.utils.TemporaryDirectory() as tempdir:
        for table in tables:
            my_handler._save_page(pdf_filename, table.page, tempdir)
            tmp_file_path = os.path.join(tempdir, f'page-{table.page}.pdf')
            layout, dim = camelot.utils.get_page_layout(tmp_file_path)
            htext_objs = camelot.utils.get_text_objects(layout, ltype="horizontal_text")
            titles.append(get_closest_text(table, htext_objs))  # Might be None

    return titles, tables

参见:https://github.com/atlanhq/camelot/issues/395