使用Camelot进行Python PDF解析并提取表标题

时间:2019-10-01 13:04:23

标签: python pdfminer tabula python-camelot

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

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

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

我想提取写在表格上方的文本,即具体,如下图所示。

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

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以直接创建莱迪思解析器

            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),提取的表也具有bbox对象。您可以找到最接近表格顶部的组件,然后提取文本。

答案 1 :(得分:1)

这是我非常糟糕的实现,只是为了让某人可以笑并受到启发去做更好的并为伟大的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