【问题标题】:iTextSharp parse tableiTextSharp 解析表
【发布时间】:2019-11-11 11:27:05
【问题描述】:

使用 iTextSharp v5.5.13

我有大量的 PDF 文件需要解析。其中大约 5% 的人有一张表格,里面有我也需要的数据。

表格如下所示:

大多数时候我需要的行被解析为
2 januari 15 januari € 49,49 € 21,57 € 15,09 € 34,39

我可以使用它。我按空间分割,它可以工作。
但有时月份名称有多余的空格:janu ari

我知道我可以重写策略来摆脱这些额外的空间。我已经将它与 pdf 的其余部分 (ITextExtractionStrategy) 一起使用,但对于此表,我使用的是矩形策略:

var rect = new System.util.RectangleJ(70, 425, 460, 200);
RenderFilter[] filter = { new RegionTextRenderFilter(rect) };
ITextExtractionStrategy strategy =
    new FilteredTextRenderListener(new MyLocationTextExtractionStrategy(), filter);
var lines = PdfTextExtractor.GetTextFromPage(reader, pageNumber, strategy).Split('\n');

我的覆盖看起来像这样:

public class MyLocationTextExtractionStrategy : LocationTextExtractionStrategy
{
    protected override bool IsChunkAtWordBoundary(TextChunk chunk, TextChunk previousChunk)
    {
        var dist = chunk.DistanceFromEndOf(previousChunk);
        return dist < -chunk.CharSpaceWidth || dist > chunk.CharSpaceWidth / 2.0f;
    }
}

我在谷歌上找到了这个。但这并不能解决我的问题。
在janu aridist大于-chunk.CharSpaceWidth的情况下,我不知道下一步该怎么做。

请让我知道什么时候我不应该对这个表使用矩形策略,而是使用不同的方法。

【问题讨论】:

  • 蛮力方法怎么样?您是否希望此类表中的数据始终采用这种格式?总是有月份的名字吗?这些是可以预见的。让我们尝试跳出框框思考。你如何去掉所有空格,然后你的字符串变成2januari15januari€49,49€21,57€15,09€34,39。用正则表达式解析并不难。 ([0-9]){1,2}(a-z)*([0-9]){1,2}(a-z)*(€[0-9]{1-},[0-9]{2})(€[0-9]{1-},[0-9]{2})(€[0-9]{1-},[0-9]{2})。我没有测试这个正则表达式,我相信它可以进一步完善。
  • 感谢@AmedeeVanGasse 建议使用蛮力方法。使用这个正则表达式似乎对我有用:new Regex(@"([0-9]{1,2})([a-z]*)([0-9]{1,2})([a-z]*)(€[0-9]{1,},[0-9]{2})(€[0-9]{1,},[0-9]{2})(€[0-9]{1,},[0-9]{2})(€[0-9]{1,},[0-9]{2})")
  • 理论上你可以用 (januari|februari|maart|april|mei|juni|juli|augustus|september|oktober|november|december) 捕捉月份,但无论如何,这只是过早的优化,([a-z]*) 也可以完成这项工作。
  • 我会把我的评论变成答案。 :)

标签: pdf itext


【解决方案1】:

如果您在此类表中的数据始终采用相同的格式,那么您可以采用不同的方法:只需接受 MyLocationTextExtractionStrategy 向您抛出的任何数据,然后将该数据处理成某种格式你可以使用。

在这种情况下,您的数据始终是:

  • 2组:
    • 1 位或 2 位数字(月份中的某天)
    • 一些字符(月份名称)
  • 4 组:
    • 欧元符号
    • 一些数字(至少一个)
    • 逗号
    • 2 位数

在2 januari 15 januari € 49,49 € 21,57 € 15,09 € 34,39 中,空格是分隔符,但对于结构良好的数据,您甚至不需要空格。所以只要删除它们,然后你的数据就会变成2januari15januari€49,49€21,57€15,09€34,39。

现在您可以对一些捕获组使用正则表达式,将您的数据处理成可口的内容。

  • 2组:
    • [0-9]{1,2}
    • [a-z]*
  • 4 组:
    • €
    • [0-9]{1,}
    • ,
    • [0-9]{2}

正如您在 cmets 中自己写的,一个可能的正则表达式可能是:

new Regex(@"([0-9]{1,2})([a-z]*)([0-9]{1,2})([a-z]*)(€[0-9]{1,},[0-9]{2})(€[0-9]{1,},[0-9]{2})(€[0-9]{1,},[0-9]{2})(€[0-9]{1,},[0-9]{2})")

【讨论】:

  • 我已将您的答案标记为解决方案。它的效果甚至比预期的要好,因为我有时也会得到一些一年有 4 位数的行。我已经对 RegEx 进行了更改,现在这些行也被正确解析了。
  • 非常高兴!
猜你喜欢
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 2022-07-26
  • 1970-01-01
相关资源
最近更新 更多