9

我需要使用 iText 从 pdf 文件中提取文本。

问题是:一些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(); }
    }
}

你能帮我完成任务吗?

4

6 回答 6

29

我是 iText 文本提取子系统的作者。你需要做的是开发你自己的文本提取策略(如果你看看是如何PdfTextExtractor.getTextFromPage实现的,你会发现你可以提供一个可插入的策略)。

您将如何确定列的开始和停止位置完全取决于您 - 这是一个难题 - PDF 没有任何列的概念(哎呀,它甚至没有单词的概念 - 只是将默认策略提供的文本提取非常棘手)。如果您提前知道列在哪里,那么您可以在文本渲染侦听器回调上使用区域过滤器(iText 库中有执行此操作的代码,最新版本的 iText In Action 书中提供了详细示例) .

如果您需要从任意数据中获取列,那么您需要完成一些算法工作(如果您有一些工作,我很乐意看看)。关于如何解决这个问题的一些想法:

  1. 使用与默认文本提取策略 (LocationAware...) 中使用的算法类似的算法来获取单词列表和 X/Y 位置(请务必考虑旋转角度)
  2. 对于每个单词,在页面的整个高度上画一条假想的线。扫描以相同 X 位置开始的所有其他单词。
  3. 扫描时,还要寻找与 X 位置相交的单词(但不要从 X 位置开始)。这将为您提供页面上列开始/停止 Y 位置的潜在位置。
  4. 拥有 X 和 Y 列后,您可以采用区域过滤方法

另一种可能同样可行的方法是分析绘图操作并寻找长的水平和垂直线(假设列以类似表格的格式划分)。目前,iText 内容解析器没有针对这些操作的回调,但可以毫无困难地添加它们。

于 2010-10-27T07:04:25.313 回答
1

除非文件使用结构化内容,否则表格在 PDF 中不作为结构存在。你了解什么是PDF文件吗?我在http://www.jpedal.org/PDFblog/?p=228上写了一篇解释文本提取问题的博客文章

于 2010-10-27T07:27:19.833 回答
1

您也可以尝试 PdfBox,但这一切都可以追溯到 PDF 中缺乏结构 - 它主要是一种用于显示的最终文件输出格式。

于 2010-10-27T07:28:31.313 回答
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);
   }
}

在stackoverflow上已经提出了与此相关的问题!

于 2016-10-06T16:39:21.637 回答
0

出于数据提取目的,您从中提取的文件非常复杂。有表格,图像,多个,列。您将需要特殊的算法来确定阅读顺序并处理表格数据。

你想在这里实现什么?您可以改用商业 OCR 引擎,让它完成所有艰苦的工作,然后从那里处理数据。

于 2010-10-27T05:30:31.443 回答
0

我知道我的回答有点晚了。但我正在使用以下代码从 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" );

}

于 2014-02-13T17:19:10.330 回答