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
相关产品推荐
相关产品推荐

