首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用PDFBox解析PDF文件(尤其是带有表格的文件)

使用PDFBox解析PDF文件(尤其是带有表格的文件)
EN

Stack Overflow用户
提问于 2010-07-08 20:59:21
回答 16查看 113.2K关注 0票数 77

我需要解析一个包含表格数据的PDF文件。我使用PDFBox来提取文件文本,以便稍后解析结果(字符串)。问题是,对于表格数据,文本提取不能像我预期的那样工作。例如,我有一个包含这样的表的文件(7列:前两列总是有数据,只有一列复杂度列有数据,只有一列财务列有数据):

代码语言:javascript
运行
复制
+----------------------------------------------------------------+
| AIH | Value | Complexity                     | Financing       |
|     |       | Medium | High | Not applicable | MAC/Other | FAE |
+----------------------------------------------------------------+
| xyz | 12.43 | 12.34  |      |                | 12.34     |     |
+----------------------------------------------------------------+
| abc | 1.56  |        | 1.56 |                |           | 1.56|
+----------------------------------------------------------------+

然后我使用PDFBox:

代码语言:javascript
运行
复制
PDDocument document = PDDocument.load(pathToFile);
PDFTextStripper s = new PDFTextStripper();
String content = s.getText(document);

这两行数据将像这样提取:

代码语言:javascript
运行
复制
xyz 12.43 12.4312.43
abc 1.56 1.561.56

最后两个数字之间没有空格,但这不是最大的问题。问题是我不知道最后两个数字是什么意思:中,高,不适用?MAC/Other,FAE?我没有数字和它们的列之间的关系。

我不需要使用PDFBox库,所以使用其他库的解决方案就可以了。我想要的是能够解析文件,并知道每个解析的数字的含义。

EN

回答 16

Stack Overflow用户

发布于 2010-08-13 05:47:34

您需要设计一种算法来以可用的格式提取数据。无论您使用哪个PDF库,您都需要执行此操作。字符和图形是通过一系列有状态的绘制操作来绘制的,即移动到屏幕上的这个位置并绘制字符'c‘的字形。

我建议您扩展org.apache.pdfbox.pdfviewer.PDFPageDrawer并覆盖strokePath方法。从那里,您可以截取水平和垂直线段的绘制操作,并使用该信息来确定表的列和行位置。然后,只需设置文本区域并确定在哪个区域中绘制了哪些数字/字母/字符。由于您知道区域的布局,因此您将能够辨别提取的文本属于哪一列。

此外,在视觉上分隔的文本之间可能没有空格的原因是,PDF通常不会绘制空格字符。相反,文本矩阵被更新,并发出“移动”的绘制命令,以绘制下一个字符和与上一个字符分开的“空间宽度”。

祝好运。

票数 20
EN

Stack Overflow用户

发布于 2013-07-01 06:02:49

您可以在PDFBox中按区域提取文本。如果您使用的是Maven,请参阅pdfbox-examples工件中的ExtractByArea.java示例文件。代码片段看起来像这样

代码语言:javascript
运行
复制
   PDFTextStripperByArea stripper = new PDFTextStripperByArea();
   stripper.setSortByPosition( true );
   Rectangle rect = new Rectangle( 464, 59, 55, 5);
   stripper.addRegion( "class1", rect );
   stripper.extractRegions( page );
   String string = stripper.getTextForRegion( "class1" );

问题是首先要得到坐标。我已经成功地扩展了普通的TextStripper,覆盖了processTextPosition(TextPosition text),打印出了每个字符的坐标,并确定了它们在文档中的位置。

但有一个简单得多的方法,至少如果你用的是Mac电脑。在预览中打开⌘I以显示检查器,选择裁剪选项卡并确保单位为点,从工具菜单选择矩形选择,然后选择感兴趣的区域。如果您选择一个区域,检查器将向您显示坐标,您可以将其舍入并馈送到Rectangle构造函数参数中。您只需使用第一种方法确认源在哪里。

票数 15
EN

Stack Overflow用户

发布于 2012-09-23 01:15:20

对我来说可能太晚了,但我认为这并不难。您可以扩展PDFTextStripper类并覆盖writePage()和processTextPosition(...)方法。在您的例子中,我假设列标题总是相同的。这意味着您知道每个列标题的x坐标,并且可以将数字的x坐标与列标题的x坐标进行比较。如果它们足够接近(您必须测试以确定有多接近),那么您可以说该数字属于该列。

另一种方法是在编写每个页面后截取"charactersByArticle“矢量:

代码语言:javascript
运行
复制
@Override
public void writePage() throws IOException {
    super.writePage();
    final Vector<List<TextPosition>> pageText = getCharactersByArticle();
    //now you have all the characters on that page
    //to do what you want with them
}

了解您的列之后,您可以对x坐标进行比较,以确定每个数字所属的列。

数字之间没有任何空格的原因是您必须设置单词分隔符字符串。

我希望这对你或其他可能正在尝试类似事情的人有用。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3203790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档