[杂谈] 从PDF文件中进行表格抽取(tabula || paddle-pp-structure)

介绍

  近期遇到了需要从电子文档中进行内容提取的任务,具体来说就是期望从PDF文件中进行表格抽取,本文主要介绍 tabula-javapaddlepaddlepp-structure 两种方案。

思路

  本文设定原文件是 pdf 类型的文件,如果是 word 类型的文件,可以使用 documents4j 等技术将 doc/docx 类型的文件转换为 pdf ,最终采用相同的技术方案

  对 pdf 进行操作的技术有很多: pdfboxitextSpireAspose 等等。

  通过对比发现: 1、 itext 如果用于商业用途,需要进行授权申请;2、Spire、Aspose都有转换限制,部分收费;3、pdfbox相对宽松,可免费试用,并且有 tabula-java 版本可以进行表格提取;

  另一种思路是增加机器学习/深度学习相关的模型,通过前期的技术积累,可采用 paddlepaddle 的 pp-structure 进行表格识别操作。

tabula-java

  使用 tabula-java 进行 pdf 的表格提取功能,示例代码如下所示。

  通过对比, tabula-java 对标准的表格提取质量最高,如果表格的线不完全(类似 三线表 这种),最终提取效率很低,极端情况下会提取不出来表格数据。

  引入 JAR,并进行代码测试。

public void getTableInfo() throws IOException {
    InputStream in = new FileInputStream(new File("alexgaoyh-table.pdf"));
    try (PDDocument document = PDDocument.load(in)) {
        SpreadsheetExtractionAlgorithm sea = new SpreadsheetExtractionAlgorithm();
        PageIterator pi = new ObjectExtractor(document).extract();
        while (pi.hasNext()) {
            Page page = pi.next();
            List<Table> tables = sea.extract(page);
            // fix 相比于官网的示例,这里多了一步操作,进行了一下去重。
            tables = tables.stream().distinct().collect(Collectors.toList());
            for (Table table : tables) {
                List<List<RectangularTextContainer>> rows = table.getRows();
                for (List<RectangularTextContainer> cells : rows) {
                    for (RectangularTextContainer content : cells) {
                        System.out.print(content.getText().replace("\r", " ") + "|");
                    }
                    System.out.println();
                }
            }
        }
    }
}

pp-structure

  为了解决 tabula-java 在进行表格提取的不足(类似三线表的情况,提取质量不高),对比使用 pp-structure。

  请点击 环境安装

  请点击 模型下载

  英文文档和中文文档采用不同的模型,具体的命令行命令如下所示

python3 predict_system.py \
    --image_dir=/home/alex/paddlepaddle/en_table.pdf \
    --det_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/en_PP-OCRv3_det_infer \
    --rec_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/en_PP-OCRv3_rec_infer \
    --rec_char_dict_path=../ppocr/utils/en_dict.txt \
    --table_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/en_ppstructure_mobile_v2.0_SLANet_infer \
    --table_char_dict_path=../ppocr/utils/dict/table_structure_dict.txt \
    --layout_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/picodet_lcnet_x1_0_fgd_layout_infer \
    --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \
    --vis_font_path=../doc/fonts/simfang.ttf \
    --recovery=True \
    --output=/home/alex/paddlepaddle/output/
    
    
python3 predict_system.py \
    --image_dir=/home/alex/paddlepaddle/ch_table.pdf \
    --det_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/ch_PP-OCRv3_det_infer \
    --rec_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/ch_PP-OCRv3_rec_infer \
    --rec_char_dict_path=../ppocr/utils/ppocr_keys_v1.txt \
    --table_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/ch_ppstructure_mobile_v2.0_SLANet_infer \
    --table_char_dict_path=../ppocr/utils/dict/table_structure_dict_ch.txt \
    --layout_model_dir=/home/alex/paddlepaddle/PaddleOCR-release-2.6/ppstructure/inference/picodet_lcnet_x1_0_layout_infer \
    --layout_dict_path=../ppocr/utils/dict/layout_dict/layout_publaynet_dict.txt \
    --vis_font_path=../doc/fonts/simfang.ttf \
    --recovery=True \
    --output=/home/alex/paddlepaddle/output/

英文识别结果对照(首先是版面恢复,其次是表格识别结果): 图片无法正常查看的话, 访问
pp-structure-en-recovery.png
pp-structure-en-table-excel.png

中文识别结果对照(首先是版面恢复,其次是表格识别结果): 图片无法正常查看的话, 访问
pp-structure-ch-recovery.png
pp-structure-ch-table-excel.png

总结

  采用 tabula-java 进行 pdf 中表格提取的话,对表格的形式有要求,类似三线表的提取,质量不高。

  采用 paddlepaddle 的 pp-structure 进行表格提取的话,可以解决 tabula-java 的不足,产业应用的话需要再包一层外部接口。

参考

  1. https://aistudio.baidu.com/aistudio/modelsdetail?modelId=18
  2. https://github.com/tabulapdf/tabula-java
  3. https://gitee.com/alexgaoyh/pap-base/blob/v1/src/test/java/com/pap/base/util/pdf/TabulaPDFTable.java
  4. https://gitee.com/alexgaoyh/pap-docs/tree/master/md/other/pp-structure-output/structure/
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Python的第三方库PyPDF2或者pdfminer来读取PDF文件表格。其,PyPDF2可以读取PDF文件的文本内容,而pdfminer可以解析PDF文件的结构信息,包括表格。可以根据具体需求选择合适的库进行操作。 ### 回答2: 要实现Python读取PDF文件表格,可以使用pdfplumber库。以下是实现的步骤: 1. 首先,安装pdfplumber库。可以使用pip命令在终端或命令提示符运行以下命令安装: ``` pip install pdfplumber ``` 2. 导入pdfplumber库。 ```python import pdfplumber ``` 3. 使用pdfplumber打开一个PDF文件。 ```python with pdfplumber.open("file.pdf") as pdf: # 读取第一页 first_page = pdf.pages[0] ``` 4. 通过extract_table()方法提取表格。 ```python # 提取表格 table = first_page.extract_table() # 打印表格内容 for row in table: print(row) ``` 提取出的表格将被存储为一个嵌套列表,其每个元素是表格的一行。你可以根据需要进行进一步的处理和分析。 5. 运行程序并读取PDF表格的数据。 完整的代码示例如下: ```python import pdfplumber with pdfplumber.open("file.pdf") as pdf: # 读取第一页 first_page = pdf.pages[0] # 提取表格 table = first_page.extract_table() # 打印表格内容 for row in table: print(row) ``` 请确保将 "file.pdf" 替换为你要读取的PDF文件的路径。 ### 回答3: Python可以使用第三方库来实现对PDF文件表格的读取和提取数据。 其一个常用的库是`tabula-py`,它是基于Java的`Tabula`提供了Python接口。`tabula-py`可以解析PDF表格,并将其转换为pandas DataFrame。以下是一个使用`tabula-py`读取PDF文件表格的示例代码: ``` import tabula # 使用tabula库读取PDF文件表格 df = tabula.read_pdf('file.pdf', pages='all') # 打印提取出的PDF表格内容 print(df) ``` 在上述代码,`read_pdf`函数用于读取PDF文件表格,并接收`pages`参数用于指定读取的页面范围(若不指定,则默认为读取所有页面)。读取后的数据将被转换为`pandas DataFrame`格式,并赋值给变量`df`。最后,使用`print`函数打印出提取出的PDF表格内容。 需要注意的是,`tabula-py`并不能处理所有的PDF文件。对于复杂的或被图片扫描的PDF文件,`tabula-py`可能无法正确处理表格。在这种情况下,可能需要使用更复杂的PDF解析库,如`PyPDF2`或`pdfplumber`。 除了`tabula-py`,还有其他一些PDF处理库,如`PyPDF2`和`pdfplumber`,也可以用于读取PDF文件表格。这些库提供了更多的灵活性和功能,但在使用上可能需要一些更复杂的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值