如何从收据收据的 Google OCR 转储文本 csv 文件中提取特定数据
How can I extract specific data from an Google OCR dump text csv file of till receipts
我只是学习 Python 机器学习的初学者。我在自学NLP,遇到了问题。我有一个带有 OCR 读取收据(100 次观察)的 csv 文件……每个单元格一张收据。一张收据的示例如下(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 @ .80
each
3.60
.45
9 SUBTOTAL
TOTAL
.45
REWARDS SAVINGS
.00
Fresh Food
5619
Lorem'''
虽然收据通常是非结构化的(即有些收据比其他收据有更多的行和辅助信息),但有 3 件事在其布局中非常结构化,我正在尝试提取该信息:小计金额(总是出现在 TOTAL 之前),TOTAL 金额(总是出现在 SUBTOTAL 之后),以及购买的商品列表(总是出现在 ABN 号码之后并在 'Qty' 之前结束)
我是这样开始的:
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', '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', '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())
小计
总计
现在我正在尝试获取金额...所以小计前的数字 (9) 和总计后的数字 ($80.45)...我尝试遍历文本列表并尝试正则表达式,但我无法得到我想要的....此外,我对如何提取购买的物品感到困惑('ABN 88 000 014 675' 和 'Qty' 之间的文本字符串,尽管拆分已经拆分了 ABN 和数字也是不同的词......所以它又是一个问题。
我做错了什么?我该如何解决这个问题?
我想到了遍历文本:
for sentence in text:
(但再一次,那又怎样...如何到达我想要的行)
任何帮助将不胜感激。
你可以使用正则表达式
(?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
问题没有指定产品的位置。据推测,它可以在小计和总计之前或之后。正是出于这个原因,我在字符串开始锚 ^
之后的正前瞻中捕获了它们。前瞻不会将引擎的内部字符串指针移到字符串开头之外,确保找到小计和总计(如果存在)。
正则表达式执行以下操作。
(?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
我对上面的空格进行了转义,使它们更显眼。
我只是学习 Python 机器学习的初学者。我在自学NLP,遇到了问题。我有一个带有 OCR 读取收据(100 次观察)的 csv 文件……每个单元格一张收据。一张收据的示例如下(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 @ .80
each
3.60
.45
9 SUBTOTAL
TOTAL
.45
REWARDS SAVINGS
.00
Fresh Food
5619
Lorem'''
虽然收据通常是非结构化的(即有些收据比其他收据有更多的行和辅助信息),但有 3 件事在其布局中非常结构化,我正在尝试提取该信息:小计金额(总是出现在 TOTAL 之前),TOTAL 金额(总是出现在 SUBTOTAL 之后),以及购买的商品列表(总是出现在 ABN 号码之后并在 'Qty' 之前结束)
我是这样开始的:
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', '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', '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())
小计
总计
现在我正在尝试获取金额...所以小计前的数字 (9) 和总计后的数字 ($80.45)...我尝试遍历文本列表并尝试正则表达式,但我无法得到我想要的....此外,我对如何提取购买的物品感到困惑('ABN 88 000 014 675' 和 'Qty' 之间的文本字符串,尽管拆分已经拆分了 ABN 和数字也是不同的词......所以它又是一个问题。
我做错了什么?我该如何解决这个问题? 我想到了遍历文本:
for sentence in text:
(但再一次,那又怎样...如何到达我想要的行)
任何帮助将不胜感激。
你可以使用正则表达式
(?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
问题没有指定产品的位置。据推测,它可以在小计和总计之前或之后。正是出于这个原因,我在字符串开始锚 ^
之后的正前瞻中捕获了它们。前瞻不会将引擎的内部字符串指针移到字符串开头之外,确保找到小计和总计(如果存在)。
正则表达式执行以下操作。
(?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
我对上面的空格进行了转义,使它们更显眼。