如何从Azure Computer Vision API OCR识别的零售收据文本提取结构化数据
我来分享一套实践过的方案,从Azure Computer Vision OCR输出的收据文本里提取商家、购买日期、税费、总计这些结构化数据,核心是结合规则匹配+针对性优化——毕竟零售收据格式五花八门,但核心字段的规律还是有迹可循的。
第一步:获取并预处理OCR输出文本
先把Azure OCR返回的内容整理成方便后续处理的格式:
- 调用Computer Vision的OCR接口后,从返回的
readResult里提取所有行的文本,要么按顺序拼接成完整字符串,要么保留每行的独立文本(后者更适合逐行匹配字段)。 - 做简单预处理:统一转成小写、去除多余空格和打印乱码符号,减少匹配时的干扰。
第二步:针对每个字段设计匹配逻辑
商家名称
商家名一般在收据最顶部,是1-2行无数字/日期的显眼文本,还常带有特定关键词:
- 取OCR结果的前3-5行,过滤掉包含金额符号($、¥等)或日期格式的行,剩下的大概率就是商家名。
- 优先匹配带
store、market、cafe、restaurant这类关键词的行。
示例Python代码片段:
def extract_merchant(ocr_lines): merchant_candidates = [] keywords = ["store", "market", "supermarket", "cafe", "restaurant"] for line in ocr_lines[:5]: line_lower = line.lower() if any(keyword in line_lower for keyword in keywords) and not any(char in line_lower for char in ["$", "/", "-"]): merchant_candidates.append(line.strip()) return " ".join(merchant_candidates) if merchant_candidates else "Unknown Merchant"
购买日期
日期格式相对固定,结合关键词+正则就能精准匹配:
- 常见格式有
MM/DD/YYYY、DD/MM/YYYY、YYYY-MM-DD,还常伴随date、purchased on这类关键词。 - 用正则+日期解析库辅助识别,示例代码:
import re from dateutil import parser def extract_date(ocr_text): # 先尝试正则匹配明确格式 date_patterns = [ r'\b\d{2}/\d{2}/\d{4}\b', r'\b\d{4}-\d{2}-\d{2}\b', r'(date:|purchased on:)\s*(\d{2}/\d{2}/\d{4})', ] for pattern in date_patterns: match = re.search(pattern, ocr_text.lower()) if match: return match.group(2) if len(match.groups())>1 else match.group(0) # 正则没匹配到的话,用dateutil尝试自动解析 try: parsed_date = parser.parse(ocr_text, fuzzy=True).strftime("%Y-%m-%d") return parsed_date except: return "Unknown Date"
税费
税费常伴随tax、sales tax、vat关键词,后面紧跟金额:
- 用正则匹配关键词+金额的组合,示例代码:
def extract_tax(ocr_text): tax_patterns = [ r'(tax|sales tax|vat)\s*[:$]?\s*(\d+\.\d{2})', r'(\d+\.\d{2})\s*(tax|sales tax|vat)' ] for pattern in tax_patterns: match = re.search(pattern, ocr_text.lower()) if match: # 提取数字部分 return match.group(2) if match.group(2).replace('.','').isdigit() else match.group(1) return "Unknown Tax"
总计
总计一般在收据底部,带total、grand total、amount due关键词,且是金额最大的项:
- 优先检查OCR结果的最后5行,结合正则匹配,示例代码:
def extract_total(ocr_lines): total_patterns = [ r'(total|grand total|amount due)\s*[:$]?\s*(\d+\.\d{2})', r'(\d+\.\d{2})\s*(total|grand total)' ] # 从底部往上找,提高准确率 for line in reversed(ocr_lines[-5:]): line_lower = line.lower() for pattern in total_patterns: match = re.search(pattern, line_lower) if match: amount = match.group(2) if match.group(2).replace('.','').isdigit() else match.group(1) return f"${amount}" if not amount.startswith('$') else amount return "Unknown Total"
第三步:边缘情况优化
- 针对格式特别奇葩的收据,可以引入简单的文本分类模型,或者直接用Azure Form Recognizer(专门针对收据/表单的服务,比通用OCR更擅长结构化提取)。
- 加入校验逻辑:比如总计应该等于商品金额总和+税费(如果能提取商品金额的话),用这个逻辑验证结果准确性。
- 缓存常见商家的收据格式(比如沃尔玛、星巴克),写专用匹配规则,进一步提升准确率。
第四步:整合完整流程
把上面的函数整合起来,形成一站式提取流程:
def extract_receipt_data(azure_ocr_response): # 从Azure OCR响应中提取每行文本 ocr_lines = [line.text for line in azure_ocr_response.readResult.blocks[0].lines] ocr_text = "\n".join(ocr_lines) return { "merchant": extract_merchant(ocr_lines), "purchase_date": extract_date(ocr_text), "tax": extract_tax(ocr_text), "total": extract_total(ocr_lines) }
内容的提问来源于stack exchange,提问作者user3116069
相关产品推荐
相关产品推荐

