我正在使用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时,为什么输出文本有差异?
答案 0 :(得分:2)
虽然在截图中,行看起来像是它们各自处于恒定水平,
实际上他们并非如此。 '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
在这种情况下,您需要一种文本提取策略,以不同方式识别行。如果你是使用HorizontalTextExtractionStrategy
或HorizontalTextExtractionStrategy2
(取决于您的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
值,因此允许一点点差异