itext: как настроить извлечение текста?

Я использую iText 5.5.8 для Java. Следуя стандартным процедурам извлечения текста, т. Е.

PdfTextExtractor.getTextFromPage(reader, pageNumber)

Я был удивлен, обнаружив несколько ошибок в выводе, в частности, все буквы d выглядят как o.

Так как же на самом деле работает извлечение текста в iText? Это какое-то OCR?

Я заглянул под капот, пытаясь понять, как работает TextExtractionStrategy, но я не мог понять многого. SimpleTextExtractionStrategy, например, кажется, просто определяет наличие строк и пробелов, тогда как он TextRenderInfo предоставляет текст, вызывая некоторый метод decode в поле font GraphicsState, и это все, что я мог сделать, не получив серьезной мигрени. .

Так кто мой мужчина? Какой класс следует переопределить или какой параметр следует настроить, чтобы можно было сказать iText: «Эй, вы читаете все d неправильно!»

редактировать:

образец PDF-файла можно найти по адресу http://www.fpozzi.com/stampastopper/download/ имя файла 0116_LR.pdf К сожалению, не могу поделиться прямой ссылкой. Это базовый код для извлечения текста

import java.io.File;
import java.io.IOException;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;

public class Import
{

    public static void importFromPdf(final File pdfFile) throws IOException
    {
        PdfReader reader = new PdfReader(pdfFile.getAbsolutePath());

        try
        {

            for (int i = 1; i <= reader.getNumberOfPages(); i++)
            {
                System.out.println(PdfTextExtractor.getTextFromPage(reader, i));
                System.out.println("----------------------------------");
            }

        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            reader.close();
        }
    }

    public static void main(String[] args)
    {
        try
        {
            importFromPdf(new File("0116_LR.pdf"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

редактировать после ответов @blagae и @mkl

Прежде чем начать возиться с iText, я попробовал извлечь текст из Apache PDFBox (проект, похожий на iText, который я только что отверг), но у него есть та же проблема.

Понимание того, как эти программы обрабатывают текст, выходит за рамки моего стремления, поэтому я написал простой метод извлечения текста из необработанного содержимого страницы, то есть того, что стоит между маркерами BT и ET.

import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.itextpdf.text.io.RandomAccessSourceFactory;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.RandomAccessFileOrArray;
import com.itextpdf.text.pdf.parser.ContentByteUtils;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;

public class Import
{

    private final static Pattern actualWordPattern = Pattern.compile("\\((.*?)\\)");

    public static void importFromPdf(final File pdfFile) throws IOException
    {
        PdfReader reader = new PdfReader(pdfFile.getAbsolutePath());

        Matcher matcher;
        String line, extractedText;
        boolean anyMatchFound;
        try
        {
            for (int i = 1; i <= 16; i++)
            {
                byte[] contentBytes = ContentByteUtils.getContentBytesForPage(reader, i);
                RandomAccessFileOrArray raf = new RandomAccessFileOrArray(new RandomAccessSourceFactory().createSource(contentBytes));
                while ((line = raf.readLine()) != null && !line.equals("BT"));

                extractedText = "";
                while ((line = raf.readLine()) != null && !line.equals("ET"))
                {
                    anyMatchFound = false;
                    matcher = actualWordPattern.matcher(line);
                    while (matcher.find())
                    {
                        anyMatchFound = true;
                        extractedText += matcher.group(1);
                    }
                    if (anyMatchFound)
                        extractedText += "\n";
                }
                System.out.println(extractedText);
                System.out.println("+++++++++++++++++++++++++++");
                String properlyExtractedText = PdfTextExtractor.getTextFromPage(reader, i);
                System.out.println(properlyExtractedText);
                System.out.println("---------------------------");
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            reader.close();
        }
    }

    public static void main(String[] args)
    {
        try
        {
            importFromPdf(new File("0116_LR.pdf"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

По-видимому, по крайней мере в моем случае, символы верны. Однако порядок слов или даже букв беспорядочный, на самом деле очень беспорядочный, поэтому этот подход также непригоден.

Что меня действительно удивляет, так это то, что все методы, которые я пробовал до сих пор для извлечения текста из PDF-файлов, включая копирование / вставку из Adobe Reader, что-то напортачили.

Я пришел к выводу, что самый надежный способ получить приличное извлечение текста также может быть самым неожиданным: хорошее распознавание текста. Теперь я пытаюсь: 1) преобразовать pdf в изображение (PDFBox отлично справляется с этим - даже не пытайтесь попробовать pdf-renderer) 2) OCR этого изображения Я опубликую свои результаты через несколько дней.


person Henry Chinaski    schedule 03.01.2016    source источник
comment
Пожалуйста, поделитесь этим PDF-файлом. Скорее всего, в нем уже есть ошибки, пусть и скрытые.   -  person mkl    schedule 03.01.2016
comment
Когда я нажимаю ссылку на ваш PDF-файл, я получаю код состояния 403.   -  person Brian Snow    schedule 04.01.2016
comment
спасибо mkl, добавлена ​​ссылка на PDF (извините, на итальянском)   -  person Henry Chinaski    schedule 04.01.2016
comment
@brian, извините, Брайан, вы должны добавить имя файла 0116_LR.pdf (не хотите, чтобы файл был виден поисковыми системами)   -  person Henry Chinaski    schedule 04.01.2016
comment
@HenryChinaski Что меня действительно удивляет, так это то, что все методы, которые я пробовал до сих пор для извлечения текста из PDF-файлов, включая копирование / вставку из Adobe Reader, что-то напортачили. Причина в том, что ваш PDF-файл намеренно пытается ввести в заблуждение экстрактор текста. В результате следование передовым методам приведет к ошибкам.   -  person mkl    schedule 08.01.2016
comment
@mkl Я не совсем уверен в преднамеренности шифрования слов. PDF-файлы, над которыми я работаю, были созданы Adobe Indesign (я знаю, потому что они написаны внутри PDF-файла), что означает, что они были вручную скомпилированы каким-то графическим дизайнером. Случайность в расположении слов может отражать порядок, в котором указанный человек добавил текстовые слои к источнику, а странное отображение символов может быть результатом какого-то непостижимого программного решения. Доступность текста - это проблема, которую любое программное обеспечение определенного назначения не может намеренно игнорировать (например, преобразование текста в речь для слабовидящих).   -  person Henry Chinaski    schedule 09.01.2016
comment
преднамеренность - проблема, указанная @blagae, является преднамеренной, я не говорю здесь о порядке. Adobe Indesign (я знаю, потому что он написан внутри pdf) - это не должно быть правдой. В частности, программное обеспечение, указанное в файле, не обязательно должно быть единственным программным обеспечением, используемым в файле.   -  person mkl    schedule 09.01.2016


Ответы (2)


Ваш входной документ был создан странным (но «законным») способом. В ресурсах есть отображение Unicode, которое сопоставляет произвольные глифы с точками Unicode. В частности, номер символа 0x64, d в ASCII, отображается на глиф с точкой Unicode 0x6f (UTF-8), которая равна o, в этом шрифте. Само по себе это не проблема - с этим может справиться любой просмотрщик PDF-файлов, - но это странно, потому что все другие используемые глифы не «перекрестно отображаются». например символ 0x63 отображается в точку Unicode 0x63 (которая равна c) и т. д.

«Неверный

Теперь по той причине, что Acrobat правильно извлекает текст (кроме пробела), а остальные идут не так. Для этого нам нужно углубиться в синтаксис PDF:

[p, -17.9, e, -15.1, l, 1.4, l, 8.4, i, -20,  m, 5.8, i, 14, st, -17.5, e, 31.2, ,, -20.1,  a] TJ
<</ActualText <fffffffeffffffff00640064> >> BDC
5.102 0 Td
[d, -14.2, d] TJ
EMC

Это указывает программе просмотра PDF-файлов напечатать p-e-l-l-i- -m-i-st-e- -a в первой строке кода и d-d после этого в четвертой строке. Однако d отображается на o, что, по-видимому, является проблемой только для извлечения текста. Acrobat правильно извлекает текст, потому что есть маркер содержимого /ActualText, который говорит, что все, что мы пишем между маркерами BDC и EMC, необходимо анализировать как dd (0x64,0x64).

Итак, чтобы ответить на ваш вопрос: iText делает это на том же уровне, что и многие уважаемые зрители, которые все игнорируют маркер /ActualText. За исключением Acrobat, который его уважает и отменяет сопоставление ToUnicode.

И чтобы действительно ответить на ваш вопрос: iText в настоящее время занимается анализом маркера /ActualText, но, вероятно, пройдет некоторое время, прежде чем он попадет в официальный выпуск.

person blagae    schedule 04.01.2016
comment
большое спасибо! Я ничего не знаю о внутренней структуре PDF-файлов, и я бы никогда не понял этого сам. Теперь я пытаюсь подумать о возможном обходном пути ... не обязательно чистом, мощном решении, но я должен предположить, что это странное сопоставление может быть другим - или может вообще отсутствовать - в следующем PDF-файле (у меня есть абсолютно не знаю, как создаются эти PDF-файлы). Любое предложение? Например, есть ли способ получить это отображение через iText? - person Henry Chinaski; 05.01.2016
comment
Ах, значит, эта проблема, по сути, дублирует эту. - person mkl; 05.01.2016
comment
Вы можете перейти к сопоставлению ToUnicode, но компьютер не может догадаться, что определенное сопоставление отключено, потому что во многих ситуациях все сопоставления нетривиальны и необходимы для извлечения текста. Лучше всего подумать о написании собственной iText TextExtractionStrategy, как показано по ссылке в ответе @mkl - person blagae; 05.01.2016

Вероятно, это связано в первую очередь с тем, как PDF-файл с оптическим распознаванием текста был обработан, а не с тем, как iTextSharp анализирует содержимое PDF-файла. Попробуйте скопировать / вставить текст из PDF в Блокнот и посмотреть, происходит ли преобразование «ds -> os». Если это так, вам нужно будет сделать следующее при синтаксическом анализе текста из этого конкретного PDF-файла:

  1. Определите все вхождения строки «os».
  2. Решите, является ли слово, составляющим которого является данный экземпляр «os», является допустимым английским / немецким / испанским / словом.
  3. Если это правильное слово, ничего не делайте.
  4. Если это НЕ допустимое слово, выполните обратное преобразование «os -> ds» и снова проверьте словарь на выбранном вами языке.
person Brian Snow    schedule 04.01.2016
comment
Попробуйте скопировать / вставить текст из PDF в Блокнот, и, к удивлению, все буквы правильные ... (извините, мне нужно вернуться к моей настоящей работе - вздох - увидимся через несколько часов!) - person Henry Chinaski; 04.01.2016
comment
Когда я это делаю, все буквы неправильные - есть много случаев ошибок распознавания. Например, на странице 16 у вас есть строка pelli miste, addolcenti, которая вставляется в Блокнот как pelli miste, aooolcenti, - person Brian Snow; 04.01.2016
comment
Я получаю pelli miste, добавляю olcenti (из Adobe Acrobat Pro XI) и pelli miste, aooolcenti как в Sumatra PDF, так и в Foxit Reader - person blagae; 04.01.2016
comment
@blagae Понятно. Прочитав ваш ответ, мой ответ кажется очень неправильным. Как вы думаете, мне следует удалить его? Или мне оставить это здесь для потомков? - person Brian Snow; 04.01.2016
comment
@BrianSnow. У меня нет проблем с тем, чтобы оставить его здесь, потому что ваш ответ с одинаковой вероятностью будет правильным для общего случая. Любой, кто в будущем будет искать в Google правильные поисковые запросы, может захотеть узнать, что несовершенное задание OCR также является очень вероятной первопричиной. - person blagae; 04.01.2016
comment
спасибо, Брайан, к сожалению, поиск в словаре будет проблематичным, потому что некоторые слова являются торговыми марками и, по всей вероятности, они не будут распознаны. Я буду рассматривать этот путь как последнее средство. - person Henry Chinaski; 05.01.2016