4

我有一个asp.net Core 2.0 C#应用程序可以读取/解析 PDF 文件并获取文本。在此我想读取具有特定标签名称的特定值。您可以看到下图我想获取数字的值171857并将其Invoice存储在数据库中。 在此处输入图像描述

我尝试使用下面的代码来阅读 pdf iTextSharp

using (PdfReader reader = new PdfReader(fileName))
        {
            StringBuilder sb = new StringBuilder();

            ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
            for (int page = 0; page < reader.NumberOfPages; page++)
            {
                string text = PdfTextExtractor.GetTextFromPage(reader, page + 1, strategy);
                if (!string.IsNullOrWhiteSpace(text))
                {
                    sb.Append(Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(text))));
                }
            }

            var pdfText = sb.ToString();
        }

pdfText变量中,我将从 pdf 中获取所有文本内容,但这似乎不是获取发票编号的正确方法。有没有其他方法可以通过它的标签名称从 pdf 中读取特定内容,就像我们将提供标签名称一样Invoice,它将返回值171857作为其他 3rd 方 pdf 阅读器库的示例?

任何帮助或建议将不胜感激。

谢谢

4

3 回答 3

6

我帮助一位朋友从 Excel arc 生成的 pdf 发票中提取了类似的值。我为此答案创建了一张 Excel 发票并将其打印为 PDF 文件并压缩以供下载以进行测试。

接下来我将使用一个名为PDFClown的开源免费库。这是它的nuget包。

到目前为止一切顺利,我所做的是扫描所有 pdf 文档(例如发票可以是一页或多页),将每个内容添加到字符串列表中。

下一步我找到索引(发票编号索引可能在列表中的第 10 个元素中,在我们的例子中是索引 1),它指的是发票价值,我将其称为标签或标签。

因此,我没有您的 pdf 文件,我即兴创作并添加了一个名为(或任何其他名称)“ INVOICE ”的独特标签。在这种情况下,发票编号位于发票标签之后。所以我找到“INVOICE”标签的索引并将索引加1这是因为发票编号跟随发票标签。这样,在这种情况下,我将选择发票文本 0005 并将其作为值 5 返回。这样,您可以获取每个文本/值后跟我们列表中扫描的任何标签的内容,并以您需要的方式返回。

因此,您需要稍微使用一下以使其 100% 适合您的 pdf 文件。

所以这是我压缩的测试文件 Excel 和 Pdf 。下载它以供您测试。

这是代码:

public class InvoiceTextExtraction
{
    private List<string> _contentList;

    public void GetValueFromPdf()
    {
        _contentList = new List<string>();
        CreatePdfContent(@"C:\temp\Invoice1.pdf");

        var index = _contentList.FindIndex(e => e == "INVOICE") + 1;
        int.TryParse(_contentList[index], out var value);
        Console.WriteLine(value);
    }


    public void CreatePdfContent(string filePath)
    {
        using (var file = new File(filePath))
        {
            var document = file.Document;

            foreach (var page in document.Pages)
            {
                Extract(new ContentScanner(page));
            }
        }
    }

    private void Extract(ContentScanner level)
    {
        if (level == null)
            return;

        while (level.MoveNext())
        {
            var content = level.Current;
            switch (content)
            {
                case ShowText text:
                {
                    var font = level.State.Font;
                    _contentList.Add(font.Decode(text.Text));
                    break;
                }
                case Text _:
                case ContainerObject _:
                    Extract(level.ChildLevel);
                    break;
            }
        }
    }
}

从 pdf 文件中提取的输入。代码扫描返回以下元素:

INVOICE
0005

PAYMENT DUE BY:
4/19/2019
.etc
.
.
.
Tax
USD TOTAL
171857
18 september 2019

这是结果

5

该代码的灵感来自此链接

于 2019-09-18T19:15:17.023 回答
4

假设发票标签和发票编号嵌入为 PDF 中的文本而不是位图。

我能想到的一种方法是使用Spire.PDF并提取标签的位置,然后找到写在该位置正下方的数字。如果您拥有要处理的所有 PDF 的相同模板,这将相对简单。

于 2019-09-18T13:06:45.470 回答
0

从答案中不清楚是否pdfText会包含发票编号以及文本的其余部分,但我会假设它会包含。如果没有,那么您将需要 OCR,这完全是另一种野兽。

在这种情况下,我的第一直觉是构建一个正则表达式 ( ^\d{6}$) 并尝试将其应用于页面上的所有文本。如果只有一个匹配项(发票编号),那就太好了!否则,如果它匹配更多的东西,你可以找到所有的出现并寻找一个模式。例如,如果客户的 ID 也与该正则表达式匹配,您可以提取所有包含匹配数字的行,并丢弃所有包含其他信息的行(可能所有带有客户 # 的行也有特定日期例如格式)。基本上找到正则表达式可以匹配的所有出现,并尝试找到规则以排除所有你不关心的出现。

于 2019-09-18T14:15:26.263 回答