Python 发票解析:REST API 指南
本指南将演示如何通过一个简单的 REST API 调用,用 Python 从任意发票图片中提取结构化的 JSON 字段、行项目和可验证的坐标数据。
从发票中提取结构化数据是一项常见但令人头疼的任务。你可能有一堆扫描的收据或供应商发票,格式是 JPEG 或 PNG,需要从中提取发票号、总金额和每个行项目,用于会计或数据分析。大多数 OCR 工具只是输出一堆杂乱的文本,你不得不依靠脆弱的正则表达式来艰难地重构数据结构。
其实有更直接的方法:调用一个 REST API,它能直接返回你需要的结构化 JSON,并且每个值都能追溯到其在页面上的精确位置。下面的交互式演示展示了最终效果。点击左侧的任何字段,即可在发票上看到其对应位置的高亮显示。

Each value with a box carries a verified on-page location — bbox + 4-point vertices + match_ratio — on a 0–1000 normalized grid (0,0 top-left → 1000,1000 bottom-right), the same shape the live API returns. Hover a field to trace it back to the pixels it came from.

space-ocr 不是一个需要安装的库,而是一个纯粹的 HTTP 服务。整个过程非常简单:准备一张发票图片,将其发送到 POST /ocr/fields 接口,并定义你希望返回的数据结构(schema)。你可以指定诸如 invoice_number、total_due 这样的字段,以及一个包含描述和价格等列的 line_items 表格。API 会返回一个与你定义的结构完全匹配的、干净的 JSON 对象。
API 对每个字段的返回结果不仅包含文本值(例如 invoice_number 的值是 "20250430-001"),还包括其坐标和置信度分数。这个 match_ratio 值反映了提取的文本与页面上识别到的字符的匹配程度,为你提供了一个可靠的数据质量信号。下面的 Python 脚本将从头演示如何实现这一切。
import os
import base64
import requests
import json
# Get your API key from an environment variable
API_KEY = os.environ.get("SPACE_OCR_API_KEY")
IMAGE_PATH = "./path/to/your/invoice.jpg" # Path to your invoice image
API_URL = "https://api.space-ocr.com/ocr/fields"
if not API_KEY:
raise ValueError("API key not found. Set the SPACE_OCR_API_KEY environment variable.")
# Define the schema for the data you want to extract
# For line items, use type 'array' and define columns in 'children'
fields_schema = [
{"name": "supplier", "type": "string", "description": "The name of the company that issued the invoice."},
{"name": "invoice_number", "type": "string"},
{"name": "issue_date", "type": "date"},
{"name": "total_due", "type": "number"},
{
"name": "line_items",
"type": "array",
"description": "All items listed in the invoice table.",
"children": [
{"name": "item_description", "type": "string"},
{"name": "unit_price", "type": "number"},
{"name": "quantity", "type": "number"},
{"name": "line_total", "type": "number"}
]
}
]
# Read the image file and encode it in base64
with open(IMAGE_PATH, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode('utf-8')
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
payload = {
"image": base64_image,
"imageType": "base64",
"fields": fields_schema
}
print(f"Sending request for {IMAGE_PATH}...")
response = requests.post(API_URL, headers=headers, json=payload)
if response.status_code == 200:
result = response.json()['data']
print("\n--- Extracted Invoice Data ---")
for field_name, field_data in result.items():
if isinstance(field_data, list):
print(f"\n{field_name}:")
for i, row in enumerate(field_data):
print(f" - Item {i+1}:")
for col_name, col_data in row.items():
print(f" {col_name}: {col_data['value']} (Confidence: {col_data['match_ratio']:.2f})")
else:
print(f"{field_name}: {field_data['value']} (Confidence: {field_data['match_ratio']:.2f})")
# Bounding box is available at field_data['bbox']
# e.g., print(f" bbox: {field_data['bbox']}")
else:
print(f"Error: {response.status_code}")
print(response.text)为了确保准确性,space-ocr 并不完全依赖语言模型的输出。模型会返回文本值以及它在页面上使用了哪些词的提示。然后,引擎会将提取出的值与页面上实际的 OCR 符号进行逐字符匹配。这个过程会生成 match_ratio 置信度分数(≥ 0.85 即可认为是高置信度匹配)和最终的边界框。所有的坐标(xmin, ymin, xmax, ymax)都经过归一化处理,范围在 0-1000 之间,这样就与原始图像的分辨率无关了。
API 按调用次数计费,而不是按字段数量或页面复杂度。每次图片处理费用为 $0.05,如果请求未能成功返回结果则不收取任何费用。新注册账户每月可获得 100 次免费扫描额度。
- 获取您的 API 密钥注册一个免费的 space-ocr 账户,在控制面板的设置中找到您的 API 密钥。密钥以 'spocr_' 开头。
- 准备您的发票图片将您的发票保存为常见的图片文件,如 JPEG 或 PNG。记下文件路径,以便在脚本中使用。
- 定义您的数据结构 (Schema)在您的 Python 脚本中创建一个 JSON 数组,用它来定义您想要提取的字段的名称和类型,包括任何行项目表格。
- 编写 Python 脚本使用 requests 库编写一个脚本,读取图片文件,将其转换为 base64 编码,然后通过 POST 方法发送到 https://api.space-ocr.com/ocr/fields。请确保在 Authorization 请求头中包含您的 API 密钥。
- 运行脚本并处理 JSON执行您的脚本。它将打印出结构化的 JSON 响应,您可以随后将其加载到数据库、会计软件或分析工具中。