当前位置: 首页 > 知识库问答 >
问题:

iText:如何调整文本提取?

壤驷英叡
2023-03-14

我使用的是iText 5.5.8 for Java。遵循默认的、简单的文本提取过程,即。

PdfTextExtractor.getTextFromPage(reader, pageNumber)

我很惊讶地在输出中发现了几个错误,特别是所有字母ds都变成了OS。

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的项目,我刚刚发布了)中提取文本,但它确实存在同样的问题。

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();
        }
    }
}

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

共有1个答案

单于越
2023-03-14

您的输入文档是以一种奇怪(但‘合法’)的方式创建的。参考资料中有一个Unicode映射,它将任意字形映射到Unicode点。特别是,ASCII中的字符号0x64(D)映射到该字体中Unicode point 0x6f(UTF-8)的字形,即O。这本身不是问题--任何PDF浏览器都可以处理--但这很奇怪,因为所有其他使用的字形都不是“交叉映射”的。例如,字符0x63映射到Unicode点0x63(即C)等。

现在的原因是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
<</ActualText <fffffffeffffffff00640064> >> 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标记,但在正式发布之前可能需要一段时间。

 类似资料:
  • 问题内容: 我要在pdf文件中添加一个水印。水印是.bmp图像,并且是2290 x3026。尝试调整此图片的大小以适合页面时,我遇到很多麻烦,有人有什么建议吗? 这是方法的输出。 我会与你们共享pdf图片,但不幸的是我不能。 我应该尝试改用.jpg吗?我真的不知道iText如何处理不同的图像扩展名。 问题答案: 您可以使用另一种方法:“手动”调整图像大小(即通过图像处理软件),而不是通过iText

  • 我有一个水印,我想放在我的pdf中。水印是一个。bmp图像,为2290 x 3026。我在调整图片大小以适应页面时遇到了很多问题,有人有什么建议吗? 下面是方法的输出。 我想和你们分享pdf的图片,但不幸的是我不能。 我是否应该尝试使用。改为jpg?我真的不知道iText处理不同图像扩展的效果如何。

  • 问题内容: 我需要使用iText从pdf文件中提取文本。 问题是:一些pdf文件包含2列,当我提取文本时,我得到一个文本文件,其中的列作为结果合并(即同一行中两列的文本) 这是代码: 你能帮我完成这个任务吗? 问题答案: 我是iText文本提取子系统的作者。您需要做的是开发自己的文本提取策略(如果您看一下如何实现的话,就会发现您可以提供可插拔的策略)。 您将如何确定列的开始和停止位置完全取决于您-

  • 我有一个swift文件,有几叠,其中上面的文字行为怪异,我想不明白为什么“控制器”的背景颜色——文字一直延伸到屏幕的末端,我该如何调整背景的高度?

  • 我正在使用Rest-Assured和GSON进行自动化测试,并且需要验证POST请求响应中返回的PDF文件的内容。文件的内容各不相同,可以包含任何内容,从文本到文本和表格,或者文本和表格和图形。就字形内容而言,每个页面都可能不同,而且很可能会不同。我只关心pdf页面上的所有文本——无论是纯文本,还是表格中的文本,或者是与图像相关的文本(或者是图像中的文本)。由于请求返回的所有pdf都是不同的,我无

  • 我的布局文件中确实有一个。与此类似: 上述实现的代码是: 我想让“小写文本”中的文本。我该怎么做?