python解析pdf,pdfplumber和tabula

最近做了一个需要解析财报pdf的项目,财报的格式大致一样,但是具体细节会有略微不同。

原本是使用pdfplumber来做,做到一半,发现 pdfplumber对于分页了的表格处理很不友好。

原本处理分页的表格,是将上一页的最后一个表格和下一页的第一个表格拼接,但是 pdfplumber 解析的表格出现乱序的情况,最后一个表格的位置出现在解析出的表格列表中间位置,导致合并表格数据失败。

所以中途又重新开始找解析框架,找到了 tabula,这个对于表格处理的某些方面比 pdfplumber 好,至少不会出现表格乱序的情况。

但是这个框架只支持pdf表格解析,不支持文字解析,所以最终还是 pdfplumber 和 tabula 混合使用。

总结来说:

pdfplumber:

优点:

  1. 对于文字的解析非常优秀,没有发现错字漏字的情况
  2. 对于普通表格的解析也很棒

缺点:

  1. 对于表格分页的情况处理很薄弱
  2. 合并单元格的表格解析会不够理想,但是效果还是要比tabula好。
  3. 有一个可视化表格工具,但那个工具巨难装,我装了一天半都没成功。

tabula:

优点:

  1. 专门用于处理pdf里的表格,对于表格分页的情况很理想
  2. 表格结果使用pandas的DataFrame数据格式包装,处理数据很强大。
  3. 有一个可视化应用exe,安装即可用(我没用过

缺点:

  1. pandas的DataFrame很强大是没错,但是对于不熟悉的人来说学习成本也很高。
  2. 合并单元格的表格形式,解析效果非常差劲,数据出现过缺失和乱序的情况
  3. 是java编写的,所以依赖于jdk

简单示例:

pdfplumber,文档地址:https://github.com/jsvine/pdfplumber

# 解析pdf
with pdfplumber.open("abc.pdf") as pdf:
    # 拿到第一页的对象
    page = parse_pdf.pages[0]
    # 拿到这一页的文本数据
    text = page.extract_text()
    # 拿到这一页的所有表格数据
    tables = page.extract_tables()
    # 遍历表格
    for t_index in range(len(tables)):
        table = tables[t_index]
        # 遍历每一行的数据
        for data in table:
            print(data)

tabula,文档地址:https://aegis4048.github.io/parse-pdf-files-while-retaining-structure-with-tabula-py

# 解析表格, stream表示流模式识别(建议),guess为猜测,pages是页面下标,从1开始
# multiple_tables是需不需要识别多个表格
tables = tabula.read_pdf(pdf_path, stream=True, guess=True, pages=    [1,2],multiple_tables=True)
    # 遍历表
    for table in tables:
        # 通过表格内置下标迭代器来遍历下标(也可能不是下标,而是id
        for index in table.index:
            # 获取下标所属那一行的值
            data = table.loc[index].values

彩蛋(tabula 表格去除全部为空的行和列):

def format_data_frame(table):
    """
    格式化data_frame表格,删除全部为空的行和列
    :return:
    """
    all_data = table.isna()
    for t_index in all_data.index:
        data = all_data.loc[t_index].values
        if all(data):
            table = table.drop([t_index], axis=0, inplace=False)

    for clo_name in all_data.columns:
        data = all_data[clo_name]
        if all(data):
            table = table.drop(clo_name, axis=1, inplace=False)
    return table

 

你可能感兴趣的:(python)