前端工程师 后段工程师
经营自己的“乐趣”之一就是处理会计。
现在,为了生存,我尝试了一些类似的操作:
一件无聊的事情是整理我必须支付的收据和发票:差旅费,书本费,会议费等。您明白了。
为什么我需要使用软件在PDF文件中查找日期
理想情况下,我希望有一个工具可以将收据与银行对账单中的行进行匹配,并生成一些报告,这些报告可能会使我的业务顾问感到非常高兴。
这样做的第一步是拥有一个工具,该工具可以使一堆PDF可以将日期与它们关联。 一旦获得日期,我便知道要考虑的银行对账单的哪几行,并且可以进行匹配(也许还要考虑金额)。
第一步:从PDF中提取文本
有两种可能的情况:PDF已经包含文本,或者PDF是简单的图像,我们需要使用OCR技术识别文本。
在第一种情况下,事情相对容易。 我们使用PDFBox提取文本:
fun getTextInPdf(fileName: String): List<PieceOfText> {
val reader = PdfReader(FileInputStream(File(fileName)))
val n = reader.numberOfPages
var i = 0
val listener = MyTextRenderListener()
val processor = PdfContentStreamProcessor(listener)
while (i<n) {
val page = reader.getPageN(i + 1)
val resourcesDic = page.getAsDict(PdfName.RESOURCES)
processor.processContent(ContentByteUtils.getContentBytesForPage(reader, i + 1), resourcesDic)
i++
}
reader.close()
return listener.process()
}
但是,当然,现实生活总是会带来惊喜。 有些PDF每段包含一个块(太棒了!),而另一些PDF 每个字母则包含一个块。 这意味着我们必须查看每个字母的位置,看看它是否与另一个字母相邻。 在这种情况下,我们需要将它们合并以获得单词。
如果PDF中没有文本,则需要采用OCR技术。 我使用过用C ++编写的tesseract 。 为了在JVM中使用它,我使用了javacpp-presets 。
一旦获得了文本块,就需要将其分成单词序列。 这部分相对容易,但并不像预期的那么琐碎,因为我们需要跟踪每个单词的确切位置。 因此,在单词中分割一个块时,需要进行一些数学运算才能找到每个单词的边界。
第二步:识别日期
我们现在有很多话。 我们需要查看它们并找到与日期相对应的单词序列。
现在,日期可能以各种奇怪的格式出现。 还请考虑我有英文(英国和美国),法语,德语和意大利语的收据。
让我们看一些例子。
首先是经典的DD / MM / YY:
- 15/04/2016
- 18-06-2016
- 2016年1月1日
有时您可以找到YY / MM / DD来代替:
- 2016-05-13
该月份可以用任何语言的字母表示:
- 2016年5月7日
- 2016年6月18日
- 2016年4月22日
- 2016年6月1日
- 2016年4月12日
也可以缩写为:
- 2016年4月14日
- 2016年4月12日
当然,有些日期无法确定,因为美国人在某个时候认为将日期的月份和日期倒置是个好主意。 因此,如果我读2/3/2016,则可能是3月2日或2月3日。 这意味着某些日期是不明确的。
第三步:确定哪个日期是订单的日期
现在,发票可以包含许多不同的日期。 考虑以下示例:
一个日期的顺序(在法国COMMANDE)的声音,另一种是公司的登记日期。 这绝对是我们不感兴趣的日期。
还有其他示例:
或再次:
我们如何处理这种情况?
好吧,我们使用了一系列启发式方法,这些方法在大多数情况下似乎都有效。 最有力的方法之一是在日期附近寻找有意义的单词,例如, 制造/发票/ fattura或命令/ 突击队/领队。 我们还可以使用字体大小和日期在页面上的位置。
这些技巧总是奏效吗? 没有。
他们经常工作吗? 是的,他们有。
结论
首先,让我与大家分享我对美国人选择的日期格式的热烈赞赏。 我觉得这是个好主意,一点也不愚蠢和不幸。 实际上,这是造成痛苦的主要原因,也是造成错误的首要原因。
我的大部分收据都是电子格式,其中包含文字。 在少数需要使用OCR的情况下,它似乎工作得足够好。
最后,我对这个原型非常满意,因为经过一些调整后,它似乎可以在90%的时间内正确猜出。 不错,真不错。
哦,嗯,我想我得回到我的会计了。
您是否想自动化一些事情以简化生活?
翻译自: https://www.javacodegeeks.com/2016/09/engineer-supposed-survive-accounting.html
前端工程师 后段工程师