You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中使用PDFTable/PDFTableExtractor读取PDF:依赖、方法及表格提取咨询

嘿,我来帮你搞定这个PDF表格提取的问题!结合你之前用Apache PDFBox的经验,我分几个部分给你讲清楚:

一、所需Maven依赖/Jar包

你提到的PDFTable或PDFTableExtractor类,Apache PDFBox核心库并没有内置,不过有两种常用方案适配你的需求:

方案1:Apache PDFBox + 第三方表格提取扩展

这个方案和你之前的PDFBox使用习惯完全兼容,依赖如下:

<!-- PDFBox核心依赖 -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.32</version> <!-- 建议用最新稳定版 -->
</dependency>
<!-- 第三方表格提取工具,提供类PDFTableExtractor的功能 -->
<dependency>
    <groupId>io.github.millij</groupId>
    <artifactId>pdfbox-table-extractor</artifactId>
    <version>2.0.0</version>
</dependency>
<!-- 处理特殊PDF可能需要的图像IO依赖 -->
<dependency>
    <groupId>com.github.jai-imageio</groupId>
    <artifactId>jai-imageio-core</artifactId>
    <version>1.4.0</version>
</dependency>

方案2:iText 7(自带PdfTableExtractor类)

如果你明确要使用PdfTableExtractor这个类,iText 7的核心库就提供了原生支持,Maven依赖:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.2.5</version> <!-- 最新稳定版 -->
    <type>pom</type>
</dependency>

二、获取特定位置数值的方法

用PDFBox第三方扩展的示例代码

和你之前的PDFBox使用逻辑一致,上手成本低:

import io.github.millij.poi.ss.model.Table;
import io.github.millij.pdfbox.table.PdfTableExtractor;
import org.apache.pdfbox.pdmodel.PDDocument;

import java.io.File;
import java.util.List;

public class PdfTableValueExtractor {
    public static void main(String[] args) throws Exception {
        // 加载你的目标PDF文件
        File targetPdf = new File("your-uploaded-document.pdf");
        try (PDDocument doc = PDDocument.load(targetPdf)) {
            // 初始化提取器,指定要提取的页码(从0开始计数)
            PdfTableExtractor extractor = new PdfTableExtractor(doc);
            List<Table> pageTables = extractor.extractTables(0); // 提取第一页的所有表格

            // 遍历表格寻找目标数值
            for (Table table : pageTables) {
                for (List<String> row : table.getRows()) {
                    // 匹配Gross premium并获取对应数值
                    if (row.contains("Gross premium")) {
                        int headerIndex = row.indexOf("Gross premium");
                        String grossPremiumValue = row.get(headerIndex + 1).trim();
                        System.out.println("Gross premium: " + grossPremiumValue);
                    }
                    // 匹配GST
                    if (row.contains("GST")) {
                        int headerIndex = row.indexOf("GST");
                        String gstValue = row.get(headerIndex + 1).trim();
                        System.out.println("GST: " + gstValue);
                    }
                    // 匹配Total Payable
                    if (row.contains("Total Payable")) {
                        int headerIndex = row.indexOf("Total Payable");
                        String totalPayableValue = row.get(headerIndex + 1).trim();
                        System.out.println("Total Payable: " + totalPayableValue);
                    }
                }
            }
        }
    }
}

用iText 7的PdfTableExtractor示例代码

如果你更倾向于官方原生的PdfTableExtractor类,参考这个示例:

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.pdf.TableExtractor;

import java.io.File;
import java.util.List;

public class ItextTableValueExtractor {
    public static void main(String[] args) throws Exception {
        File targetPdf = new File("your-uploaded-document.pdf");
        try (PdfReader reader = new PdfReader(targetPdf);
             PdfDocument pdfDoc = new PdfDocument(reader)) {

            // 初始化表格提取器,指定页码(从1开始计数)
            TableExtractor tableExtractor = new TableExtractor(pdfDoc);
            List<Table> pageTables = tableExtractor.extractTable(1); // 提取第一页的所有表格

            for (Table table : pageTables) {
                // 遍历表格行
                for (int rowIdx = 0; rowIdx < table.getNumberOfRows(); rowIdx++) {
                    var row = table.getRow(rowIdx);
                    // 遍历单元格匹配表头
                    for (int cellIdx = 0; cellIdx < row.getNumberOfCells(); cellIdx++) {
                        String cellText = row.getCell(cellIdx).getText().trim();
                        switch (cellText) {
                            case "Gross premium":
                                String grossValue = row.getCell(cellIdx + 1).getText().trim();
                                System.out.println("Gross premium: " + grossValue);
                                break;
                            case "GST":
                                String gstValue = row.getCell(cellIdx + 1).getText().trim();
                                System.out.println("GST: " + gstValue);
                                break;
                            case "Total Payable":
                                String totalValue = row.getCell(cellIdx + 1).getText().trim();
                                System.out.println("Total Payable: " + totalValue);
                                break;
                        }
                    }
                }
            }
        }
    }
}

三、你的其他疑问解答

1. 能否原样提取带行列及表格线的格式化表格数据?

  • 如果是原生PDF表格(由PDF结构化表格元素构成,非图片扫描件):可以准确提取行列结构,部分工具还能获取单元格边界信息。提取后你可以自行将数据转换成带格式的输出(比如Markdown表格、Excel文件),表格线可以通过输出格式还原(比如Markdown用|分隔单元格)。
  • 如果是扫描件PDF(图像型表格):需要结合OCR工具(比如Tesseract)先识别文本,再提取表格结构,这种情况很难原样保留表格线,只能提取文本的行列关系。

2. 页面包含文本与表格时,能否仅读取表头及行数据?

完全可以!不管用哪种方案,提取器都会返回独立的表格对象,你可以只处理表格部分,忽略页面其他文本。而且可以通过判断行内容(比如表头通常是第一行,或包含特定关键词)来精准提取表头和数据行,过滤无关内容。

3. 提取你指定的三个数值是否可行?

当然可行!只要你的PDF是原生可编辑的(非扫描件),表格结构清晰,用上面的代码就能精准定位到Gross premium、GST、Total Payable对应的数值。如果表格位置固定,甚至可以结合你之前用的PDFTextStripperByArea先定位表格区域,再提取数值,效率更高。

内容的提问来源于stack exchange,提问作者Vengat Joy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:11:09