【问题标题】:PDFBox text extraction ligatures "fi", "fl" problem on Android StudioAndroid Studio上的PDFBox文本提取连字“fi”,“fl”问题
【发布时间】:2020-05-05 18:45:57
【问题描述】:

我在 Android Studio 库中使用这个 https://github.com/TomRoush/PdfBox-Android PDFBox 从 PDF 文档中提取文本。这就是我正在做的事情:

File pdf_file = new File(file_path);

创建文件,然后

PDDocument document = null;
document = PDDocument.load(pdf_file);

将文件加载到 PDDocument 对象中,然后

PDFTextStripper pdfStripper = new PDFTextStripper();
pdfStripper.setStartPage(...);
pdfStripper.setEndPage(...);
String page_text = pdfStripper.getText(document);

获取页面的文本内容。问题是当有例如“公司”这个词时,它会显示为“公司”。它基本上在 fi 之后放置一个空格(我猜是 fls 和其他连字)。我尝试阅读此Problems with extracting OpenTypeFont text using pdfBox,但我不明白如何解决它。没有解决方案详情。

重要提示:事实证明,在我的 PDF 文件中,我没有任何连字,例如 fi,但我有常规 fi,但它后面还有空格。解决方案尚不清楚。

PDF 文件:https://wetransfer.com/downloads/09e9036dda4a7962ccad32b1cbcd8edc20200506050349/ab4752

【问题讨论】:

  • 请分享文件。我想知道桌面版 PDFBox 是否会发生这种情况。
  • @TilmanHausherr 你好,我已经更新了我的问题,提供了下载 PDF 的链接
  • 我也遇到过这个问题,我通过搜索 fi AND fi(连字)解决了这个问题
  • @Lonzak 嗯,你是怎么解决的?您找到连字 fi 并删除它后面的空格?
  • @JingleBells 查看我发布的答案...

标签: java android-studio pdfbox text-extraction


【解决方案1】:

问题是,例如,当有“公司”这个词时,它会显示为“公司”。

原因很简单:“fi”后面有一个空格!

这是绘制示例文件中第一次出现“公司”的线条的文本绘制指令:

 [( )360.3(Mr Dursley was the director of a “)250( )110.3(rm called Grunnings, )]TJ

字节 (147) 通过字体编码映射到字形名称 fi 并通过字体的 ToUnicode 映射到Unicode 字符 U+fb01,拉丁小连字 fi。

因此,PDF 查看器显示连字字形 fi,文本提取器提取 Unicode 连字字符 fi 或扩展后的字符 f强>和

在连字之后,绘制下一个字形的起点向左移动 250 个单位,然后绘制一个空格,然后下一个起点向左移动 110.3 个单位,然后绘制“rm”。

因此,您在查看器中看不到“fi”和“rm”之间的间隙(因为向左移动会抵消空格字形的绘制),但文本提取器会提取空格字符(因为它在那里) .

您可以检查这不是 PDFBox 怪癖,例如带有复制和粘贴功能的 Adob​​e Reader 将该文本行提取为

Mr Dursley was the director of a fi rm called Grunnings,

就像 PDFBox 一样,它扩展连字并提取空格字符。

【讨论】:

  • 您可能想尝试删除所有空格并让 PDFBox 在适当的位置插入空格,如this answer 所示。
  • 感谢您的回答!所以事实证明 fi 和 rm 之间实际上存在空间,PDF 查看器使用“坐标”并忽略空间,但是当 PDFBox 提取文本时,空间实际上是存在的。是PDF文件本身的问题还是其他PDF会发生?上述评论中的建议很好,但我不确定我是否要删除所有空格并信任 PDFBox 添加它认为有必要的位置。我发现的一个解决方案是简单地查找 fi 和 fl 并在之后删除空间。据我所知,以fi或fl结尾的英语单词并不多。
  • 无论如何,我真的希望这是 PDF 文件本身和它的协调系统的问题。
  • 严格来说“启用简单正确的文本提取”不是 PDF 文件的要求,因此这本身不是问题。但是这种复杂性确实是完全没有必要的(就 PDF 标准而言);因此,如果您与 PDF 的制作人签订了合同,其中该制作人承诺通过合理的努力使文本提取成为可能,您确实可以要求他更改这一点。这实际上看起来像生产者处理连字,如应用于空格字形的变音符号。
  • 顺便说一下,您总结了 PDF 查看器使用“坐标”并忽略空格...他们不会忽略空格,他们实际上会它!但是由于我的回答中讨论的指令中的数字参数,它们在连字上绘制了空(完全透明)的空间字形,因此您在最终渲染中看不到它。
【解决方案2】:

正如评论中提到的,我曾经遇到过类似的连字问题。我不得不检查 PDF 文件中的某些字符串,并且想知道为什么它对某些字符串不起作用。经过分析,我发现这些文件包含连字,因此即使在视觉上包含它,我也找不到“Textfield”。我的解决方案是不仅要搜索 textfield,还要搜索 textfield - 所以搜索两个字符串,一个有连字,一个没有连字。

您说您想从 pdf 文件中提取文本。所以我会添加一个后处理步骤。

  1. 像现在这样提取文本
  2. 搜索所有连字,例如"fi" 和 "fi" 并将其替换为 "fi"。

我的文档在连字后没有空格 - 所以我会考虑这两种情况。并且还应考虑单词结尾的情况(例如 buffi)(那么可能是两个空格?)。

一个通用词:这个话题并不容易,因为您已经研究过。此步骤称为NFKC normalization。在 pdfbox 2.X 中,这是在内部完成的(cp. PDFBOX-2384),但在 pdfbox 1.X 中,TextNormalize.java 是 doing it

更新:

您可以尝试的另一种可能性是更改 PDFTextStripper.java。有一种方法叫做normalizeWord(...)。它将单个“fi”连字转换为“f”和“i”。在那里你可以添加

//line 1971...
//for PDFs where ligatures are followed by a space (e.g. "fi ve") 
if(word.substring(q+1,q+2).equals(" ")) {
  p = q + 2;
}
else {
  p = q + 1;
}

但我只使用 pdfbox 2.0.19 进行了尝试(看来您使用的是 1.8.X)。好消息是它仅在找到连字时应用。然而,由于以连字结尾的单词存在问题,这似乎不是一个通用的解决方案。但是在您的情况下,您应该没问题,因为每个连字后似乎始终有一个空格。

【讨论】:

  • 你确定你最后一段的意思是 itext 吗?
  • 是的,我的意思是 Pdfbox...感谢您发现这一点
  • 嗯,原来我没有连字。它是“textfield”,而不是“textfield”,所以替换方法不起作用:\ 出于某种原因,它在 fi 之后放置了一个空格,而不是 fi
  • @Lonzak 考虑到上面的消息,您是否碰巧知道修复它的方法?
  • @mkl 考虑到“fi”是 f 和 i,而不是 fi,我在 PDF 中没有连字,但在“fi”之后有一个空格。您碰巧知道解决方案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多