Странные пробелы при анализе PDF
мне нужно проанализировать PDF-документ. Я уже реализовал парсер и использовал библиотеку iText и до сих пор он работал без каких-либо проблем.
но нет, мне нужно разобрать еще один документ, который получает очень странные пробелы в середине слова. В качестве примера я получаю:
Vo rber eitung auf die Motorr adsaison. Viele Motorr adf ahr er
все смелые слова должны быть подключен, но каким-то образом парсер PDF добавляет пробелы в слова. Но когда я копирую и вставляю содержимое из PDF в текстовый файл, я не получаю эти пробелы.
сначала я думал, что это из-за библиотеки синтаксического анализа PDF, которую я использую, но и с другой библиотекой я получаю точно такую же проблему.
Я посмотрел на singleSpaceWidth
из разбираемых слов, и я заметил, что он меняется всегда тогда, когда он добавляет пробелы. Я попытался соединить их вручную. Но поскольку на самом деле нет шаблона для рекомбинации слов, это почти невозможно.
у кого-нибудь еще была аналогичная проблема или даже решение этой проблемы?
по запросу, вот дополнительная информация:
- iText версия 5.2.1
- http://prine.ch/whitespacesProblem.pdf (ссылка на pdf)
синтаксический анализ с помощью SemTextExtractionStrategy:
PdfReader reader = new PdfReader("data/SpecialTests/SuedostSchweiz/" + src);
SemTextExtractionStrategy semTextExtractionStrategy = new SemTextExtractionStrategy();
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
// Set the page number on the strategy. Is used in the Parsing strategies.
semTextExtractionStrategy.pageNumber = i;
// Parse text from page
PdfTextExtractor.getTextFromPage(reader, i, semTextExtractionStrategy);
}
здесь Метод SemTextExtractionStrategy, который фактически анализирует текст. Там я вручную добавляю после каждого проанализированного слова пробел, но каким-то образом он разделяет слова в обнаружении:
@Override
public void parseText(TextRenderInfo renderInfo, int pageNumber) {
this.pageNumber = pageNumber;
String text = renderInfo.getText();
currTextBlock.getText().append(text + " ");
....
}
вот весь класс SemTextExtraction, но там он вызывает только метод сверху (parseText):
public class SemTextExtractionStrategy implements TextExtractionStrategy {
// Text Extraction Strategies
public ColumnDetecter columnDetecter = new ColumnDetecter();
// Image Extraction Strategies
public ImageRetriever imageRetriever = new ImageRetriever();
public int pageNumber = -1;
public ArrayList<TextParsingStrategy> textParsingStrategies = new ArrayList<TextParsingStrategy>();
public ArrayList<ImageParsingStrategy> imageParsingStrategies = new ArrayList<ImageParsingStrategy>();
public SemTextExtractionStrategy() {
// Add all text parsing strategies which are later on applied on the extracted text
// textParsingStrategies.add(fontSizeMatcher);
textParsingStrategies.add(columnDetecter);
// Add all image parsing strategies which are later on applied on the extracted text
imageParsingStrategies.add(imageRetriever);
}
@Override
public void beginTextBlock() {
}
@Override
public void renderText(TextRenderInfo renderInfo) {
// TEXT PARSING
for(TextParsingStrategy strategy : textParsingStrategies) {
strategy.parseText(renderInfo, pageNumber);
}
}
@Override
public void endTextBlock() {
}
@Override
public void renderImage(ImageRenderInfo renderInfo) {
for(ImageParsingStrategy strategy : imageParsingStrategies) {
strategy.parseImage(renderInfo);
}
}
}
3 ответов
я обработал данный PDF-файл со следующим Ghostscript:
gs -o out.pdf -q -sDEVICE=pdfwrite -dOptimize=false -dUseFlageCompression=false -dCompressPages=false -dCompressFonts=false whitespacesProblem.pdf
эта команда создала файл out.pdf
, который не имеет кодировок потока, поэтому он лучше читается. Интересная часть находится в строке 52, которую я разбил на несколько строк для удобства чтения:
[
(&;&)-287.988
(672744)29.9906
(+\(%)30.01
(+!4)29.9876
(&4)-287.989
(%4)30.0039
(&1&8)-287.975
(3=\)!)-288.021
(*&4)30.0212
(&=23)-287.996
(+1%)-287.99
(\(=&)-288.011
(8&1&)-287.974
(672744)29.9906
(+\(3+=378$)-250.977
(#7\)!)
]TJ
в скобках-это текст. Я изменил некоторые из них и наблюдал за отображаемым PDF-файлом, чтобы узнать, какой символ представляет глиф. Затем я расшифровал текст:--7-->
[
(ele)-287.988
(Motorr)29.9906 ***
(adf)30.01 ***
(ahr)29.9876 ***
(er)-287.989
(fr)30.0039
(euen)-287.975
(sich)-288.021
...
]
таким образом, действительно есть пробелы между символами. В вашем случае это, вероятно, Кернинг шрифта. Теперь вопрос в том, как ваша библиотека PDF интерпретирует этот пробел, и мне кажется, что даже "отрицательные пробелы" отображаются в пробел в результирующей строке.
пробелы в pdf являются известной проблемой, как описано в ответе здесь Роландом, а также видно при первом комментарии https://issues.apache.org/jira/browse/TIKA-724
ответ, который также работал для меня, - это тот, который видел huuhungus на https://github.com/smalot/pdfparser/issues/72
который специфичен для PDFParser, и он должен изменить код, который фактически добавляет Это дополнительное пространство в PDFParser, если вы знаете, что у вас будет такая проблема:
src/Smalot/PdfParser / Object.php прокомментируйте эту строку
$text .= ' ';
не полностью исправить, но это на приемлемом
другие библиотеки также могут иметь аналогичные временные исправления, чтобы они могли помочь с этой проблемой в некоторых случаях.
поскольку документ, который у вас есть, разбит на столбцы, очевидная ошибка находится внутри
SemTextExtractionStrategy
класса. Я предполагаю, что класс ColumnDetecter надо винить, наверное, и не iText. Я могу только предположить, что он реализован на основе размера столбца, а затем извлекает текст на основе этого.
Если вы хотите только текст, то реализация может быть проще, на основе о размере столбца.