PDF в текст: iTextSharp: дубликаты страниц в результатах извлечения

Заранее спасибо.

Фон:

Я работаю над консольным приложением, которое извлекает данные из определенных разделов в документах PDF. Для этого мне сначала нужно преобразовать этот PDF-файл в строку для работы. Для этого я обратился к iTextSharp. PDF-файлы располагаются с двумя столбцами на странице, поэтому я использую SimpleTextExtractionStrategy() (я пробовал iTextSharp.text.pdf.parser.LocationTextExtractionStrategy(), но обнаружил, что это неэффективно для макета страницы).

Описание контента, преобразуемого в текст:

Страницы, с которыми у меня, кажется, возникают проблемы, имеют «заголовок», размещенный сбоку страницы. Страницы с заголовками периодически рассредоточены по документу.

Изображение макета страницы: http://postimg.org/image/b7i25v0g1/

Проблема:

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

Я бы закончил с текстом, который выглядит так:

Страница 1 Содержание

Первый заголовок

Второй заголовок

Страница 1 Содержание

Страница 2 Содержание

и Т. Д.

Вот файл в формате pdf: http://www.filedropper.com/dd35-completeadventurer

Я не женат на iTextSharp, мне просто нужен надежный способ конвертировать документы этого формата в текст. Обходной или альтернативный метод будет оценен по достоинству.

    static public string ToTxt(string @filePath)
    {
        string strText = string.Empty;
        try
        {
            PdfReader reader = new PdfReader(filePath);

            for (int page = 1; page <= reader.NumberOfPages; page++)
            {

                Widgets.ProgressBar(page);

                //Convert PDF to Text
                ITextExtractionStrategy its = new SimpleTextExtractionStrategy(); //iTextSharp.text.pdf.parser.LocationTextExtractionStrategy();
                String s = PdfTextExtractor.GetTextFromPage(reader, page, its);
                strText = strText + s;
            }
            reader.Close();
            Console.WriteLine("File Extracted");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: " + e.Message);
        }
        finally
        {
            Console.Clear();
        }
        return strText;
     }

person CodeHead    schedule 27.07.2015    source источник
comment
Хотя это и не решение вашей проблемы, см. это, почему вы хотите избавиться от всей строки перекодирования для вашего s переменная   -  person Chris Haas    schedule 27.07.2015
comment
В противном случае ваш код кажется правильным, насколько я могу судить. Сначала это звучало как эта проблема, но вы каждый раз правильно создаете новую стратегию извлечения текста. Просто для ясности: ваш вывод заставляет вас проанализировать часть страницы, затем перейти на другую страницу, а затем вернуться к первой странице, верно? Можете ли вы опубликовать фактический PDF где-нибудь?   -  person Chris Haas    schedule 27.07.2015
comment
Скорее всего, причина такого повторения контента в том, что контент действительно присутствует дважды, второй раз, возможно, за пределами страницы или в том же месте, что и в первый раз. Можете ли вы поделиться PDF, чтобы проверить это?   -  person mkl    schedule 28.07.2015
comment
Спасибо, парни. Добавил пдф.   -  person CodeHead    schedule 28.07.2015


Ответы (2)


Как уже предполагалось в комментарии, повторяющийся текст уже присутствует в содержимом PDF!

Подробности

Содержимое пар страниц, обращенных друг к другу в вашем документе, часто идентично, каждый раз содержимое всего разворота, а отдельные страницы просто отображают только левую или правую половину соответственно.

Например. рассмотрим две страницы 6 и 7. Их содержание идентично:

разворот страниц 6 и 7

заполняя область своего идентичного MediaBox. Просто установив CropBoxArtBox, BleedBox и TrimBox) в левую или правую половину соответственно , для страницы 6 отображается только ожидаемое содержимое:

страница 6

и страница 7:

страница 7

Ни структура синтаксического анализатора iText (Sharp), ни SimpleTextExtractionStrategy автоматически не ограничиваются этими полями, они извлекают весь текст, нарисованный где-либо в содержимом. Таким образом, дублируется текст.

Предотвращение дублирования текста в результате извлечения

Зная причину дублирования текста, есть несколько способов предотвратить это:

  1. Вы можете попытаться извлечь содержимое только любой другой страницы PDF. К сожалению вышесказанное справедливо не для всех страниц, по крайней мере начальные страницы (титульный лист, оглавление, ...) созданы не по описанной выше схеме, а далее в книге есть страницы-оформления, не соответствующие схеме . Таким образом, этот вариант потребует некоторого управления исключительными страницами.

  2. Вы можете извлечь содержимое каждой страницы, но сохранить содержимое ранее обработанной страницы в некоторой переменной. Теперь добавьте только что извлеченный контент к результату, если он не равен контенту предыдущей страницы.

  3. Вы можете использовать фильтры анализатора iText (Sharp). Если вы ограничите фрагменты текста, обрабатываемые вашей стратегией, только теми, которые нарисованы внутри рамки обрезки текущей страницы, вы предотвратите дублирование текста, вызванное контентом за пределами страницы. Пример фильтрации по регионам можно найти здесь: ExtractPageContentArea.java / ExtractPageContentArea.cs.

person mkl    schedule 28.07.2015
comment
Круто, я реализовал проверку страницы, и она работает как шарм. Мне это нравится, потому что это а) легко реализовать, б) оно будет работать в разных форматах (в отличие от любой другой страницы или фильтра постоянной области). Я опубликую код ниже в другом комментарии. Большое спасибо мкл! - person CodeHead; 28.07.2015

Используя второй метод mkl (проверка каждой страницы на повторение), я пришел к следующему, и он работает блестяще; легко исправить:

    string strText = string.Empty;
        try
        {
            PdfReader reader = new PdfReader(filePath);
            string prevPage = "";
            for (int page = 1; page <= reader.NumberOfPages; page++)
            {
                Widgets.ProgressBar(page);
                //Convert PDF to Text
                ITextExtractionStrategy its = new SimpleTextExtractionStrategy();
                String s = PdfTextExtractor.GetTextFromPage(reader, page, its);
                if (prevPage != s)
                    strText += s;
                prevPage = s;
            }
            reader.Close();
            Console.WriteLine("File Extracted");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: " + e.Message);
        }
        finally
        {
            Console.Clear();
        }
        return strText;
    }
person CodeHead    schedule 28.07.2015