当前位置:  开发笔记 > 编程语言 > 正文

itext:如何调整文本提取?

如何解决《itext:如何调整文本提取?》经验,为你挑选了1个好方法。

我正在使用iText 5.5.8 for Java.遵循默认的,简单的文本提取程序,即

PdfTextExtractor.getTextFromPage(reader, pageNumber)

我惊讶地发现,在输出几次失误,特别是所有的字母d的问世为Ø秒.

那么iText中的文本提取真的如何工作呢?是某种OCR吗?

我看了看引擎盖,试图掌握它是如何TextExtractionStrategy工作的,但我想不出多少.SimpleTextExtractionStrategy例如,似乎只是确定线条和空间的存在,而这TextRenderInfo是通过调用一些提供文本解码的方法GraphicsStatefont领域,这是据我可以去没有得到一个重大的偏头痛.

那么谁是我的男人?其中I类应该重写或参数我应该调整到能够告诉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复制/粘贴,搞砸了一些东西.

我得出的结论是,获得一些体面文本提取的最可靠方法也可能是最意想不到的:一些好的OCR.我现在正在尝试:1)将pdf转换为图像(PDFBox很擅长这样做 - 甚至不用去尝试pdf-renderer)2)OCR该图像我将在几天内发布我的结果.



1> blagae..:

您的输入文档是以奇怪的(但"合法的")方式创建的.资源中有一个Unicode映射,可将任意字形映射到Unicode点.特别是,dASCII中的字符编号0x64映射到Unicode点0x6f(UTF-8)的字形,即o此字体.这本身并不是问题 - 任何PDF查看器都可以处理它 - 但它很奇怪,因为使用的所有其他字形都不是"交叉映射".例如,字符0x63映射到Unicode点0x63(即c)等.

Unicode输入错误

现在因为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
< >> 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标记,但它可能需要一段时间才能进入正式版本.

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有