Android Studio 上的 PDFBox 文本提取连字 "fi"、"fl" 问题

PDFBox text extraction ligatures "fi", "fl" problem on Android Studio

我在 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);

获取页面的文本内容。问题是,当有例如单词 "firm" 时,它显示为 "fi rm"。它基本上在 fi 之后放置一个 space (我猜是 fls 和其他连字)。我尝试阅读此 Problems with extracting OpenTypeFont text using pdfBox 但我不明白如何修复它。没有解决方案的详细信息。

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

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

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

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

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

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

总而言之:题目不简单,你已经研究过了。此步骤称为 NFKC normalization. In pdfbox 2.X this is done internally (cp. PDFBOX-2384) now but in pdfbox 1.X the TextNormalize.java was 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)。好处是它仅在发现连字时应用。然而,由于以连字结尾的单词存在问题,这似乎不是一个通用的解决方案。但在你的情况下你应该没问题,因为每个连字后似乎总是有一个 space。

The issue is that when there's for example the word "firm" it displays it like "fi rm".

原因很简单:在"fi"![=14=之后一个space ]

这是在示例文件中绘制第一次出现 "firm" 的线条的文本绘制指令:

 [( )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 或扩展字符 fi.

在连字之后绘制下一个字形的起点向左移动250个单位,然后绘制一个space,然后下一个起点向左移动110.3个单位,然后"rm" 已绘制。

因此,您在查看器中看不到 "fi" 和 "rm" 之间的差距(因为向左移动抵消了 space 字形的绘制)但是文本提取器提取一个 space 字符(因为它在那里)。

您可以确认这不是 PDFBox 的怪癖,例如Adobe Reader 通过复制和粘贴将该文本行提取为

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

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