【问题标题】:How can I extract specific data from an Google OCR dump text csv file of till receipts如何从直到收据的 Google OCR 转储文本 csv 文件中提取特定数据
【发布时间】:2021-12-04 12:59:56
【问题描述】:

我只是一个学习 Python 机器学习的初学者。我正在自学 NLP,但我遇到了问题。我有一个 csv 文件,其中包含 OCR 读取直到收据(100 个观察)...每个单元格一个收据。一张收据的示例如下(csv中的信息以这种方式读取):

text = '''ㅎㅎ
Fresh Food
The fresh food people
5619 Lorem PH: 00 0000 0000
204 Some Road
TAX INVOICE - ABN 88 000 014 675
Gift Card Visa Varbl 20to500Dollars
Potato White Washed 2Kg
Nescafe Coffee Blend 43 50g
^HToblerone Milk Chocolate Bar 50g
^HOreo Cookie Original 133g
#M&Ms Crispy 145g
*HRed Rock Deli Portgse Chicken 150g
^HWrigleys Extra Pepprmint 14pc 27g
Qty
57.95
3.50
5.00
0.90
1.50
4.50
3.50
2 @ $1.80
each
3.60
$80.45
9 SUBTOTAL
TOTAL
$80.45
REWARDS SAVINGS
$10.00
Fresh Food
5619
Lorem'''

虽然收据通常是非结构化的(即,有些收据的行数和附属信息比另一个多),但有 3 件事的布局非常结构化,我正在尝试提取该信息:小计金额(总是出现在 TOTAL 之前)、TOTAL 金额(总是出现在 SUBTOTAL 之后)和购买的商品列表(总是出现在 ABN 号码之后并在“数量”之前结束)

我是这样开始的:

re.split(r'\s+', text) --->splits the string into a list of words

['ãÂ...ŽãÂ...ÂŽ', 'Freah', 'Food', 'The', 'fresh', 'food', 'people', '5619', 'Unley', 'PH :', '00', '0000', '0000', '204', 'Some', 'Road', 'TAX', 'INVOICE', '-', 'ABN', '88', '000' , '014', '675', 'Gift', 'Card', 'Visa', 'Varbl', '20to500Dollars', 'Potato', 'White', 'Washed', '2Kg', 'Nescafe', '咖啡'、'混合'、'43'、'50g'、'^HToblerone'、'牛奶'、'巧克力'、'酒吧'、'50g'、'^HOreo'、'Cookie'、'Original'、' 133g'、'#M&Ms'、'Crispy'、'145g'、'*HRed'、'Rock'、'Deli'、'Portgse'、'Chicken'、'150g'、'^HWrigleys'、'Extra'、 'Pepprmint'、'14pc'、'27g'、'数量'、'57.95'、'3.50'、'5.00'、'0.90'、'1.50'、'4.50'、'3.50'、'2'、'@ ', '$1.80', '每个', '3.60', '$80.45', '9', '小计', 'TOTAL', '$80.45', 'REWARDS', 'SAVINGS', '$10.00', '新鲜', 'Food'、'5619'、'UNLEY'、'SA'、'TCDM'、'ID.'、'Thank'、'you'、'tor'、'shopping'、'with'、'us'、' STORE'、'5619'、'POS'、'065'、'TRANS'、'8660'、'13:39'、'04/08/2021']

x = re.search('SUBTOTAL', text)
print(x.group())
y = re.search('TOTAL', text)
print(y.group())

小计

总计

现在我正在尝试获取金额...所以 SUBTOTAL (9) 之前的数字和 TOTAL 之后的数字 ($80.45)...我尝试遍历文本列表并尝试正则表达式,但我无法得到我想要的……此外,我对如何提取购买的物品感到困惑(“ABN 88 000 014 675”和“数量”之间的文本字符串,尽管拆分已将 ABN 和数字拆分为不同的词也是如此......所以这又是一个问题。

我做错了什么?我该如何解决这个问题? 我想到了循环文本:

for sentence in text:

(但又是什么......如何到达我想要的线路)

任何帮助将不胜感激。

【问题讨论】:

    标签: python regex ocr data-extraction


    【解决方案1】:

    你可以使用正则表达式

    (?s)^(?=.* ABN \d{2}(?: \d{3}){3}\n(?P<products>.*\n)Qty\n).*\n\$(?P<subtotal>\d+\.\d{2})\n\d+ SUBTOTAL\.*\nTOTAL\n\$(?P<total>\d+\.\d{2})\n
    

    捕获组products 包含产品的子字符串:

    "Gift Card Visa Varbl 20to500Dollars\nPotato White Washed 2Kg\nNescafe Coffee Blend 43 50\n^HToblerone Milk Chocolate Bar 50g\n^HOreo Cookie Original 133\n#M&Ms Crispy 145g\n*HRed Rock Deli Portgse Chicken 150g\n^HWrigleys Extra Pepprmint 14pc 27g(?.*\nz"
    

    如果需要,可以在换行符上夹板。

    捕获组subtotal 包含小计:

    9
    

    捕获组total包含总数:

    80.45
    

    Demo

    该问题未指定产品的位置。大概它可以在小计和总计之前或之后。正是出于这个原因,我在字符串开头锚^ 之后的正向前瞻中捕获了它们。该前瞻不会将引擎的内部字符串指针移动到字符串开头之外,从而确保找到小计,然后找到总计(如果存在)。

    正则表达式执行以下操作。

    (?s)             # cause periods to match all chars, including newlines
    ^                # match beginning of string
    (?=              # begin positive lookahead
      .*             # match zero or more chars
      \ ABN\         # match ' ABN '
      \d{2}          # match 2 digits
      (?:            # begin a non-capture group
        \ \d{3}      # match a space followed by 3 digits
      ){3}           # end non-capture group, execute thrice 
      \n             # match newline
      (?P<products>  # begin a capture group named 'products'
        .*           # match zero or more chars including newlines           
        \n           # match newline
      )              # end capture group
      Qty\n          # match 'Qty', newline
    )                # end positive lookahead
    .*\n             # match zero or more chars, newline
    \$\d+\.\d{2}\n   # match '$', one or more digits, period, 2 digits, newline
    (?P<subtotal>    # begin capture group named 'subtotal'
      \d+            # match one or more digits
    )                # end capture group
    \ +SUBTOTAL\n    # match one or more spaces, 'SUBTOTAL', newline
    TOTAL\n          # match 'TOTAL', newline
    \$               # match '$'
    (?P<total>       # begin capture group named 'total'       
      \d+\.\d{2}     # match one or more digits, period, 2 digits
    )                # end capture group
    \n               # match newline
    

    我已经转义了上面的空格以使它们更明显。

    【讨论】:

    • 哇...这太棒了...任何人都可以使用 regex101 吗???...我将分解您代码中的每个表达式以理解...。将极大地帮助我学习....从来不知道我们可以以这种方式使用正则表达式...分组 ....感谢一百万.....只需 1 次编辑 - 小计是篮子中的项目数,即数字 9与 SUBTOTAL 在同一行,但您的代码在前一行输出美元金额.....我如何在代码中更改它?也许像这样:*\n(?P\d + SUBTOTAL\b.
    • 温迪,我做了更正。是的,所有人都可以使用 regex101.com。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2023-03-12
    • 1970-01-01
    • 2020-04-07
    • 2011-04-04
    • 2018-09-11
    相关资源
    最近更新 更多