2010-10-26 4 views
3

Мне нужно извлечь текст из pdf-файлов с помощью iText.Извлечь столбцы текста из pdf-файла с помощью iText

Проблема в том, некоторые PDF-файлы содержат 2 колонки и когда я извлечь текст я получаю текстовый файл, в котором столбцы слиты в качестве результата (т.е. текст из обоих столбцов в одной и той же линии)

это код :

public class pdf 
{ 
    private static String INPUTFILE = "http://www.revuemedecinetropicale.com/TAP_519-522_-_AO_07151GT_Rasoamananjara__ao.pdf" ; 
    private static String OUTPUTFILE = "c:/new3.pdf"; 

    public static void main(String[] args) throws DocumentException, IOException { 
     Document document = new Document(); 
     PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(OUTPUTFILE)); 
     document.open(); 

     PdfReader reader = new PdfReader(INPUTFILE); 
     int n = reader.getNumberOfPages(); 

     PdfImportedPage page; 

     // Go through all pages 
     for (int i = 1; i <= n; i++) { 
      page = writer.getImportedPage(reader, i); 
      Image instance = Image.getInstance(page); 
      document.add(instance); 
     } 

     document.close(); 

     PdfReader readerN = new PdfReader(OUTPUTFILE); 
     for (int i = 1; i <= n; i++) { 
      String myLine = PdfTextExtractor.getTextFromPage(readerN,i); 
      System.out.println(myLine); 

      try {    
       FileWriter fw = new FileWriter("c:/yo.txt",true); 
       fw.write(myLine); 
       fw.close(); 
      }catch (IOException ioe) {ioe.printStackTrace(); } 
    } 
} 

Не могли бы вы помочь мне в решении этой задачи?

ответ

23

Я являюсь автором подсистемы извлечения текста iText. Что вам нужно сделать, так это разработать собственную стратегию извлечения текста (если вы посмотрите, как реализовано PdfTextExtractor.getTextFromPage, вы увидите, что вы можете обеспечить подключаемую стратегию).

Как вы собираетесь определить, где начинаются и останавливаются столбцы, - это сложная проблема. В PDF нет понятия столбцов (черт возьми, у него даже нет понятия слов - просто собирать извлечение текста, которое предоставляет стратегия по умолчанию, довольно сложно). Если вы знаете, где находятся столбцы, то вы можете использовать фильтр региона в обратном вызове text render listener (для этого есть код в библиотеке iText, а в последней версии книги iText In Action приведен подробный пример) ,

Если вам нужно получить столбцы из произвольных данных, у вас есть какая-то работа над алгоритмом (если у вас что-то работает, я бы хотел посмотреть). Некоторые идеи о том, как подойти к этому:

  1. Используйте алгоритм, аналогичный тому, который используется в стратегии экстракционного текста по умолчанию (LocationAware ...), чтобы получить список слов и X/Y места (не забудьте учесть угол поворота)
  2. Для каждого слова нарисуйте воображаемую линию, полную высоту страницы. Сканирование всех других слов, начинающихся с одной и той же позиции X.
  3. При сканировании также найдите слова, которые пересекают положение X (но не начинаются в позиции X). Это даст вам потенциальное место для позиционирования столбца на старт/стоп на странице.
  4. После того как вы столбец X и Y, вы можете прибегнуть к области фильтрации подхода

Другого подход, который может быть в равной степени возможно будет анализировать операции отрисовки и искать длинные горизонтальные и вертикальные линии (предполагая, что столбцы демаркированы в табличном формате). В настоящий момент анализатор содержимого iText не имеет обратных вызовов для этих операций, но можно было бы добавить их без особых трудностей.

+1

Благодаря @kevin [Как читатели PDF сделать это так хорошо?] (Http://stackoverflow.com/questions/22675690/if-identifying-text-structure-in-pdf- document-is-so-hard-how-do-pdf-reade) – david004

+2

@ david004 Я очень сомневаюсь, что читатели PDF отлично справляются со всеми PDF-файлами. Он * мог бы быть более умным с символом разделителя, который мы вставляем между словами (это то, что я подозреваю в приложениях для чтения PDF-файлов). В основном, если расстояние между символом и рядом больше определенного порога (возможно, в два раза больше ширины пробела?) Вместо символа пробела используется символ табуляции. Это может быть достаточно хорошим для многих сценариев, но определенно недостаточно для анализа общего назначения. Если бы это помогло, я мог бы посмотреть на добавление поведения вставки вкладок ... –

0

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

Что вы пытаетесь достичь здесь? Вместо этого вы можете использовать коммерческий движок OCR и позволить ему выполнять всю тяжелую работу, а затем обрабатывать данные оттуда.

0

Таблицы не существуют в виде структур в PDF, если файл не использует структурированный контент. Вы понимаете, что такое PDF-файл? Я написал статью в блоге, объясняющую проблемы извлечения текста в http://www.jpedal.org/PDFblog/?p=228

1

Вы также можете попробовать PdfBox, но все это связано с отсутствием структуры в формате PDF - в первую очередь для формата вывода конечного файла для отображения.

1

Я знаю, что мой ответ немного запоздал. Но я использую следующий код для чтения определенных страниц из файлов PDF. У меня не было проблем с чтением столбцов, без объединенного текста, каждый столбец печатается отдельно от другого.

/** 
* Get plain text from a specific page in a pdf file. 
* @param pdfPath 
* @return 
* @throws IOException 
*/ 
public static String getPageContent(String pdfPath, int pageNumber) throws IOException 
{ 
    PdfReader reader = new PdfReader(pdfPath); 

    StringWriter output = new StringWriter(); 

     try { 
      output.append(PdfTextExtractor.getTextFromPage(reader, pageNumber, new SimpleTextExtractionStrategy())); 

     } catch (OutOfMemoryError e) { 

      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    return output.toString(); 
} 

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

public static String getPageContent(String pdfPath, int pageNumber) throws IOException 
{ 

    PDDocument pdDoc = PDDocument.load(pdfPath); 
    PDPage specPage = (PDPage)pdDoc.getDocumentCatalog().getAllPages().get(0); 

PDFTextStripperByArea stripper = new PDFTextStripperByArea(); 
stripper.setSortByPosition(true); 
float width = (specPage.getMediaBox().getHeight())*25.4f; 
float height = (specPage.getMediaBox().getWidth())*25.4f; 
Rectangle rect = new Rectangle(0, 0, Math.round(width), Math.round(height)); 
stripper.addRegion("class1", rect); 
List allPages = pdDoc.getDocumentCatalog().getAllPages(); 
PDPage firstPage = (PDPage)allPages.get(pageNumber-1); 
stripper.extractRegions(firstPage); 

return stripper.getTextForRegion("class1"); 

}

1

PDFTextStream это один! По крайней мере, я могу определить значения столбцов. Раньше я использовал iText и застрял в определении стратегии. Это тяжело.

Этот api разделяет ячейки ячеек, помещая больше пробелов. Это фиксированная. вы можете поставить логику. (это отсутствовало в iText).

import com.snowtide.PDF; 
import com.snowtide.pdf.Document; 
import com.snowtide.pdf.OutputTarget; 

public class PDFText { 
    public static void main(String[] args) throws java.io.IOException { 
     String pdfFilePath = "xyz.pdf"; 

     Document pdf = PDF.open(pdfFilePath); 
     StringBuilder text = new StringBuilder(1024); 
     pdf.pipe(new OutputTarget(text)); 
     pdf.close(); 
     System.out.println(text); 
    } 
} 

Question has been asked related to this on stackoverflow!

+0

OP написал: «Мне нужно извлечь текст из pdf-файлов с помощью iText». Итак, как ваш ответ помогает ему это сделать? (Говорить, что PDFTextStream построен на нем, не учитывается.) – mkl

+0

Это продвижение платного продукта – Antony

Смежные вопросы