使用 iText7 从 PDF 中提取文本。如何提高其性能?

Sup*_*JMN 1 .net c# pdf itext

目前,我使用此代码从矩形(区域)中提取文本。

public static class ReaderExtensions
{
    public static string ExtractText(this PdfPage page, Rectangle rect)
    {
        var filter = new IEventFilter[1];
        filter[0] = new TextRegionEventFilter(rect);
        var filteredTextEventListener = new FilteredTextEventListener(new LocationTextExtractionStrategy(), filter);
        var str = PdfTextExtractor.GetTextFromPage(page, filteredTextEventListener);
        return str;
    }
}
Run Code Online (Sandbox Code Playgroud)

它有效,但我不知道这是否是最好的方法。

另外,我想知道 iText 团队是否可以改进 GetTextFromPage 以提高其性能,因为我正在处理数百个大型 PDF 页面,并且使用我当前的配置通常需要 10 多分钟才能完成。

编辑:

来自评论:似乎iText可以一次提取同一页面上多个矩形的文本,可以提高性能(批量操作往往更有效),但是如何?

更多细节!

我的目标是从多页的 PDF 中提取数据。每个页面都有相同的布局:一个包含行和列的表格。

目前,我正在使用上面的方法来提取每个矩形的文本。但是,如您所见,提取不是批处理的。它一次只是一个矩形。如何一次性提取页面的所有矩形?

mkl*_*mkl 5

正如评论中已经提到的,我很惊讶地看到 iText 7LocationTextExtractionStrategy不再包含类似于 iText 5 的LocationTextExtractionStrategy方法GetResultantText(TextChunkFilter)。这将允许您解析页面一次并从开箱即用的任意页面区域中的文本片段中提取文本。

但是有可能恢复该功能。一种选择是将其添加到LocationTextExtractionStrategy. 不过,这里的答案有点长。所以我使用了另一个选项:我使用现有的LocationTextExtractionStrategy,并且仅在GetResultantText调用中操作策略的文本块的底层列表。TextChunkFilter我没有使用通用界面,而是将过滤限制为手头的标准,即按矩形区域过滤。

public static class ReaderExtensions
{
    public static string[] ExtractText(this PdfPage page, params Rectangle[] rects)
    {
        var textEventListener = new LocationTextExtractionStrategy();
        PdfTextExtractor.GetTextFromPage(page, textEventListener);
        string[] result = new string[rects.Length];
        for (int i = 0; i < result.Length; i++)
        {
            result[i] = textEventListener.GetResultantText(rects[i]);
        }
        return result;
    }

    public static String GetResultantText(this LocationTextExtractionStrategy strategy, Rectangle rect)
    {
        IList<TextChunk> locationalResult = (IList<TextChunk>)locationalResultField.GetValue(strategy);
        List<TextChunk> nonMatching = new List<TextChunk>();
        foreach (TextChunk chunk in locationalResult)
        {
            ITextChunkLocation location = chunk.GetLocation();
            Vector start = location.GetStartLocation();
            Vector end = location.GetEndLocation();
            if (!rect.IntersectsLine(start.Get(Vector.I1), start.Get(Vector.I2), end.Get(Vector.I1), end.Get(Vector.I2)))
            {
                nonMatching.Add(chunk);
            }
        }
        nonMatching.ForEach(c => locationalResult.Remove(c));
        try
        {
            return strategy.GetResultantText();
        }
        finally
        {
            nonMatching.ForEach(c => locationalResult.Add(c));
        }
    }

    static FieldInfo locationalResultField = typeof(LocationTextExtractionStrategy).GetField("locationalResult", BindingFlags.NonPublic | BindingFlags.Instance);
}
Run Code Online (Sandbox Code Playgroud)

中心扩展是从页面中获取已经包含信息的LocationTextExtractionStrategy扩展,将LocationTextExtractionStrategy这些信息限制在给定矩形中的信息,提取文本,并将信息返回到之前的状态。这需要一些反思;我希望这对你没问题。

  • 我很高兴这段代码有帮助。* 87.6 倍 * 实际上比我希望的要快 ;)。关于反射部分:是的,图书馆创建者隐藏内部结构而不是“受保护”的趋势可能是一个 PITA ...... (2认同)