用 Python 解析發票:一份 REST API 指南
使用 Python 從發票中提取結構化資料。本指南將說明如何呼叫一個簡單的 REST API,從任何發票影像中取得 JSON 欄位、條列項目以及可供驗證的座標。
從發票中提取結構化資料是個常見卻惱人的任務。您可能有一堆掃描的收據或廠商發票,格式是 JPEG 或 PNG,而您需要從中取出發票號碼、總金額和每個條列項目,以利會計或分析之用。大多數 OCR 工具只會輸出一大堆文字,讓您得用脆弱的正規表示式(regular expressions)辛苦地重組資料結構。
其實有個更直接的方法:透過一次 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 物件。
每個欄位的回應不僅包含文字值(例如 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 的計價方式是按次計費,而非根據欄位數量或頁面複雜度。每張影像的費用為 10 日圓(約 0.05 美元),若請求未能成功產生結果則不收費。新註冊帳戶每月可獲得 100 次免費掃描額度。
- 取得您的 API 金鑰註冊一個免費的 space-ocr 帳戶,並在儀表板設定中找到您的 API 金鑰。金鑰會以「spocr_」開頭。
- 準備您的發票影像將您的發票儲存為常見的影像檔,例如 JPEG 或 PNG。記下檔案路徑以供腳本使用。
- 定義您的資料綱要在您的 Python 腳本中建立一個 JSON 陣列,用來定義您想擷取的欄位名稱和類型,包含任何條列項目表格。
- 撰寫 Python 腳本使用 requests 函式庫,撰寫一個腳本來讀取影像、將其轉換為 base64,並將 API 金鑰放在 Authorization 標頭中,向 https://api.space-ocr.com/ocr/fields 發送 POST 請求。
- 執行並處理 JSON執行您的腳本。它會印出結構化的 JSON 回應,接著您就可以將這些資料載入您的資料庫、會計軟體或分析工具中。