来自PDF的文本以不同方式吐出

时间:2016-05-18 18:16:48

标签: java parsing pdf itext pdfbox

我正在使用iText从pdf文档的页面阅读文本。 PDF中有两条完全相同的行,但解析后的输出对于两行都不同。 iText lib以不同方式吐出文本的原因是什么?两条线(字符串)的长度相同。

使用iText方法:

String text = PdfTextExtractor.getTextFromPage(reader, 1);

当我检查'文字'元素,输出如下。但是,这三行似乎在pdf中完全相同。

XXXXXX XXXXX XXXXX : XXXXX :
#*2 1
XXXXXX XXXXX XXXXX : #*3 XXXXX : 2
XXXXXX XXXXX XXXXX : XXXXX :
#15 1

编辑:额外问题: 当我使用PDFBox时,解析后的输出非常不同。使用iText与PDFBox时,为什么输出文本有差异?

1 个答案:

答案 0 :(得分:2)

虽然在截图中,行看起来像是它们各自处于恒定水平,

screenshot

实际上他们并非如此。 'XXX ...:'和'TOTAL:'部分位于 y 坐标469.45,457.95和446.45,而'#..','1'和'2'部分位于 y 坐标为468.65,457.15和445.65。

要将水平文本视为在同一行,使用默认文本提取策略(LocationTextExtractionStrategy)的iText文本提取要求 y 坐标在转换为{{{ 1}}。 (实际上这有点简化,整个图片看int

在目前的情况下,这只是中间行LocationTextExtractionStrategy.TextChunkLocationDefaultImp的情况。因此,默认文本提取结果为:

(int) 457.95 = 457 = (int) 457.15

在这种情况下,您需要一种文本提取策略,以不同方式识别行。如果你是使用HorizontalTextExtractionStrategyHorizontalTextExtractionStrategy2(取决于您的iText版本,前者适用于iText 5.5.8,后者适用于较新的iText 5.5.x版本)来自this answer,您我会得到:

XXXXXX XXXXX XXXXX : TOTAL :
#*2 1
XXXXXX XXXXX XXXXX : #*3 TOTAL : 2
XXXXXX XXXXX XXXXX: TOTAL :
#15 1

(使用TextExtraction.java测试方法XXXXXX XXXXX XXXXX : #*2 TOTAL : 1 XXXXXX XXXXX XXXXX : #*3 TOTAL : 2 XXXXXX XXXXX XXXXX: #15 TOTAL : 1 测试)

顺便说一句,这并不意味着默认情况下应该切换到testTest_pdf()。这种方法也有其缺点,特别是它查看整个页面(或至少整个页面部分,如果通过过滤器提取)宽度来查找行。因此,如果你的页面,例如有两列文本相互连接,每行只有相同的近似高度,这种策略可能会返回完全垃圾。

附录

OP在评论中提到

  

您能简单解释HorizontalTextExtractionStrategy2正在做什么吗?

在扫描页面时,此策略仅收集文本绘图说明中的文本块及其边界框坐标。

当询问结果文本时,它会在第一遍中将所有这些边界框投影到页面坐标系的 y 轴上。

在第二遍中,它将此投影图像的每个连通分量解释为单行的 y 坐标范围:它从上到下遍历这些连通分量;对于每个组件,它将所有块投影到其中,按 x 坐标对它们进行排序,在适当的位置添加空格,并将它们合并到文本行。

最后,它返回这些行的连接(中间有换行符)。

  

HorizontalTextExtractionStrategy说“此渲染器跟踪方向的单位矢量的方向和距离(垂直和平行)。文本按方向排序,然后垂直,然后平行距离。文本具有相同的垂直距离,但不同的平行距离被视为在同一条线上。“这对我来说没有多大意义。

本质上它也是一种双程策略,在第一遍中收集所有带坐标的文本块,在第二遍中将它们排列为线。不过,这种策略考虑了块的基线方向,并首先按基线角度排序。

在具有相同基线角度的块中,如果块(有界)基线位于相同(无界)线上,则认为块属于同一文本行。

被认为属于同一文本行的块然后按写入方向排序,并在适当的位置插入空格。

此策略所做的比较均基于LocationTextExtractionStrategy值,因此允许一点点差异