1

我已经通过 Java 和 PDF 论坛从 pdf 文件中的表中提取文本值,但除了JPedal之外找不到任何解决方案(它不是开源和许可的)。

所以,我想知道任何开源 API,如 pdfbox、itext 以实现与 JPedal 相同的结果。

参考。例子:

样品表

4

2 回答 2

6

在评论中,OP 澄清说他从表格中找到了他想要提取的 pdf 文件中的文本值

通过提供 X 和 Y 坐标

因此,虽然这个问题最初听起来像是从 PDF 中提取表格数据的通用提取(至少可能很困难),但实际上它本质上是关于从由坐标给定的页面上的矩形区域中提取文本。

这可以使用您提到的任何一个库(当然还有其他库)。

文字

要限制要从中提取文本的区域,可以使用RegionTextRenderFilterin a FilteredTextRenderListener,例如:

/**
 * Parses a specific area of a PDF to a plain text file.
 * @param pdf the original PDF
 * @param txt the resulting text
 * @throws IOException
 */
public void parsePdf(String pdf, String txt) throws IOException {
    PdfReader reader = new PdfReader(pdf);
    PrintWriter out = new PrintWriter(new FileOutputStream(txt));
    Rectangle rect = new Rectangle(70, 80, 490, 580);
    RenderFilter filter = new RegionTextRenderFilter(rect);
    TextExtractionStrategy strategy;
    for (int i = 1; i <= reader.getNumberOfPages(); i++) {
        strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), filter);
        out.println(PdfTextExtractor.getTextFromPage(reader, i, strategy));
    }
    out.flush();
    out.close();
    reader.close();
}

(来自 iText in Action,第 2 版的ExtractPageContentArea示例)

但请注意,iText 基于内容流中的基本文本块提取文本,而不是基于此类块中的每个单独的字形。因此,如果只有最小部分在该区域中,则处理整个块。

这可能适合您,也可能不适合您。

如果您遇到提取的内容比您想要的多的问题,您应该事先将块拆分为它们的构成字形。这个stackoverflow答案解释了如何做到这一点。

PDFBox

要限制要从中提取文本的区域,可以使用PDFTextStripperByArea,例如:

PDDocument document = PDDocument.load( args[0] );
if( document.isEncrypted() )
{
    document.decrypt( "" );
}
PDFTextStripperByArea stripper = new PDFTextStripperByArea();
stripper.setSortByPosition( true );
Rectangle rect = new Rectangle( 10, 280, 275, 60 );
stripper.addRegion( "class1", rect );
List allPages = document.getDocumentCatalog().getAllPages();
PDPage firstPage = (PDPage)allPages.get( 0 );
stripper.extractRegions( firstPage );
System.out.println( "Text in the area:" + rect );
System.out.println( stripper.getTextForRegion( "class1" ) );

(PDFBox 1.8.8 示例中的ExtractTextByArea )

于 2015-02-03T09:19:53.437 回答
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:45:29.940 回答