【发布时间】:2016-01-03 18:09:42
【问题描述】:
我正在为 Java 使用 iText 5.5.8。 遵循默认的、直接的文本提取程序,即
PdfTextExtractor.getTextFromPage(reader, pageNumber)
我惊讶地发现输出中有几个错误,特别是所有字母 ds 都输出为 os。
那么 iText 中的文本提取到底是如何工作的呢?是某种 OCR 吗?
我查看了引擎盖,试图了解TextExtractionStrategy 的工作原理,但我想不通。例如SimpleTextExtractionStrategy 似乎只是确定是否存在行和空格,而TextRenderInfo 通过在GraphicsState 的font 字段上调用一些decode 方法来提供文本,那就是尽我所能避免严重偏头痛。
那么谁是我的男人?我应该覆盖哪个类或者我应该调整哪个参数以便能够告诉 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该图像 我会在几天后发布我的结果。
【问题讨论】:
-
请分享有问题的 PDF。错误很可能已经在其中,尽管被隐藏了。
-
当我点击你的 PDF 链接时,我得到一个 403 状态码。
-
感谢 mkl,添加了 PDF 链接(抱歉,它是意大利语)
-
@brian 对不起,brian,你应该附加文件名 0116_LR.pdf(不希望文件被搜索引擎看到)
-
@HenryChinaski 真正让我吃惊的是,到目前为止,我尝试从 PDF 中检索文本的所有方法,包括从 Adobe Reader 复制/粘贴,都搞砸了 - 原因是您的 PDF 故意试图误导文本提取器。因此,遵循最佳做法将导致错误。
标签: itext text-extraction