PDFBox извлекает лигатуры текста "fi", "fl" проблема в Android Studio - PullRequest
3 голосов
/ 05 мая 2020

Я использую эту https://github.com/TomRoush/PdfBox-Android PDFBox в библиотеке Android Studio для извлечения текста из 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 и другие лигатуры). Я пробовал прочитать это Проблемы с извлечением текста OpenTypeFont с помощью pdfBox , но не понимаю, как это исправить. Подробностей решения нет.

Важно: как оказалось, в моем PDF-файле у меня нет лигатур, таких как, но у меня есть обычный fi, и все же после него есть место. Решение неясно.

PDF-файл: https://wetransfer.com/downloads/09e9036dda4a7962ccad32b1cbcd8edc20200506050349/ab4752

Ответы [ 2 ]

4 голосов
/ 11 мая 2020

Проблема в том, что когда есть, например, слово «фирма», оно отображается как «фирма».

Причина проста: Там пробел после «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 отображают глиф лигатуры , а экстракторы текста извлекают либо символ лигатуры Unicode 1025 * или после разверните символы f и i .

После этой лигатуры начальная точка для рисования следующего глифа перемещается влево на 250 единиц, затем пробел рисуется, затем следующая начальная точка перемещается влево на 110,3 единиц, а затем рисуется "rm".

* 1 034 * Таким образом, вы не видите промежутка между «fi» и «rm» в средствах просмотра (потому что ходы влево противодействуют прорисовке символа пробела), но экстракторы текста извлекают пробел (потому что он там).

Вы можете убедиться, что это не причуда PDFBox, например, Adobe Reader с копией и вставкой извлекает эту текстовую строку как

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

Как и PDFBox, он расширяет лигатуру и извлекает пространство характер.

2 голосов
/ 06 мая 2020

Как упоминалось в комментарии, у меня однажды была аналогичная проблема с лигатурами. Мне пришлось проверять файлы PDF на наличие определенных строк, и мне было интересно, почему это не сработало для некоторых. После анализа я обнаружил, что эти файлы содержат лигатуры, и поэтому я не смог найти «Текстовое поле», даже если оно визуально содержало его. Мое решение заключалось в том, чтобы искать не только textfield, но и textfield - поэтому ищите две строки, одну с лигатурой и одну без лигатуры.

Вы сказали, что хотите извлечь текст из файлов PDF. Поэтому я бы добавил этап постобработки.

  1. Извлеките текст, как вы делаете сейчас
  2. Найдите все лигатуры, например, «» и «», и замените его на «fi».

У меня были документы, в которых после лигатуры не было места, поэтому я рассмотрел оба случая. Также следует учитывать варианты окончания слов (например, «баффи») (может быть, тогда два пробела?).

Общее слово: топи c не так прост, как вы уже исследовали. Этот шаг называется NFK C нормализация . В pdfbox 2.X это делается внутренне (cp. PDFBOX-2384), но в pdfbox 1.X TextNormalize. java было это делается .

Обновление:

Еще одна возможность, которую вы можете попробовать, - это изменить 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). Хорошо, что он применяется только при обнаружении лигатуры. Однако это не может быть общим решением из-за проблем со словами, заканчивающимися лигатурой. Но в вашем случае все должно быть в порядке, поскольку после каждой лигатуры всегда остается пробел.

...