在很多企业系统中,发票录入一直是一个高频但低效率的工作。本文从真实项目出发,讲解如何通过 OCR 技术实现发票信息自动识别,并给出完整 API 接入方案。
一、为什么企业需要发票 OCR?
在财务系统、报销系统、ERP 等场景中,发票数据录入通常需要人工完成:
- 输入发票号码
- 输入发票金额
- 输入开票日期
- 输入税额
如果每天处理几十甚至上百张发票,人工成本会非常高。
常见问题包括:
- ❌ 人工录入效率低
- ❌ 容易输入错误
- ❌ 数据无法自动化
因此,越来越多系统开始使用 发票 OCR 自动识别。
二、发票 OCR 能识别哪些信息?
一张发票通常包含很多结构化信息,例如:
- 发票代码
- 发票号码
- 开票日期
- 购买方名称
- 销售方名称
- 发票金额
- 税额
- 合计金额
OCR 系统不仅要识别文字,还需要:
- 自动定位字段
- 提取关键数据
- 返回结构化 JSON
例如返回结果可能类似:
{
"invoice_number": "12345678",
"invoice_date": "2025-03-01",
"total_amount": "1000.00",
"tax_amount": "130.00"
}
三、发票 OCR 技术实现流程
完整流程通常包括以下步骤:
上传发票图片
↓
图像预处理
↓
文本检测
↓
文字识别
↓
字段结构化提取
↓
返回发票信息
其中最关键的是:
- 文本检测
- 文本识别
- 结构化解析
如果全部自研,通常需要较长研发周期。
四、发票 OCR API 接入实战
为了快速实现自动识别,可以直接接入 OCR API。
接入流程通常很简单:
Step 1:上传发票图片
前端上传图片或PDF即可:
<input type="file" />
Step 2:调用 OCR API
如果你正在做系统集成,可以先参考接口文档(通常包含多语言示例):
下面是一个最小调用示例。
发票OCR识别 Python 示例
# Python 调用代码
# API 文档地址:https://market.shiliuai.com/doc/invoice-ocr
import requests
import base64
import json
# 请求接口
URL = "https://ocr-api.shiliuai.com/api/invoice_ocr/v1"
# 图片转base64
def get_base64(file_path):
with open(file_path, 'rb') as f:
data = f.read()
b64 = base64.b64encode(data).decode('utf8')
return b64
def demo(appcode, file_path):
# 请求头
headers = {
'Authorization': 'APPCODE %s' % appcode,
'Content-Type': 'application/json'
}
# 请求体
b64 = get_base64(file_path)
data = {"file_base64": b64}
# 请求
response = requests.post(url=URL, headers=headers, json=data)
content = json.loads(response.content)
print(content)
if __name__=="__main__":
appcode = "你的APPCODE"
file_path = "本地文件路径"
demo(appcode, file_path)
发票OCR识别 Java 示例
// Java 示例
// API 文档地址:https://market.shiliuai.com/doc/invoice-ocr
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Base64;
public class Main {
public static String get_base64(String path) {
String b64 = "";
try {
// 使用Commons IO简化文件读取
byte[] content = FileUtils.readFileToByteArray(new File(path));
// 使用JDK自带的Base64
b64 = Base64.getEncoder().encodeToString(content);
} catch (IOException e) {
e.printStackTrace();
}
return b64;
}
public static void main(String[] args) {
String url = "https://ocr-api.shiliuai.com/api/invoice_ocr/v1";// 请求接口
String appcode = "你的APPCODE";
String file_path = "本地文件路径";
Map headers = new HashMap<>();
headers.put("Authorization", "APPCODE " + appcode);
headers.put("Content-Type", "application/json");
// 请求体
requestObj = new JSONObject();
requestObj.put("file_base64", get_base64(file_path));
String bodys = requestObj.toString();
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(url);
for (Map.Entry entry : headers.entrySet()) {
httpPost.addHeader(entry.getKey(), entry.getValue());
}
StringEntity entity = new StringEntity(bodys, "UTF-8");
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
int stat = response.getStatusLine().getStatusCode();
if (stat != 200) {
System.out.println("Http code: " + stat);
return;
}
String res = EntityUtils.toString(response.getEntity());
JSONObject res_obj = JSON.parseObject(res);
System.out.println(res_obj.toJSONString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
PHP 示例
// 发票OCR识别 PHP 示例
// API 文档:https://market.shiliuai.com/doc/invoice-ocr
function get_base64($path){
if($fp = fopen($path, "rb", 0)) {
$binary = fread($fp, filesize($path));// 文件读取
fclose($fp);
$b64 = base64_encode($binary);// 转base64
}else{
$b64="";
printf("%s 文件不存在", $path);
}
return $b64;
}
$url = "https://ocr-api.shiliuai.com/api/invoice_ocr/v1";
$appcode = "你的appcode";
$file_path = "文件路径";
$method = "POST";
// 请求头
$headers = array();
array_push($headers, "Authorization:APPCODE " . $appcode);
array_push($headers, "Content-Type:application/json");
// 请求体
$b64 = get_base64($file_path);
$data = array(
"file_base64" => $b64
);
$post_data = json_encode($data);
// 请求
$curl = curl_init();
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_FAILONERROR, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
$result = curl_exec($curl);
var_dump($result);
C# 示例
// 发票OCR识别 C# 示例
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MyCSharpApp
{
public class Program
{
public static string GetBase64(string path)
{
string b64 = "";
try
{
// 读取文件内容
byte[] content = File.ReadAllBytes(path);
// 转换为Base64字符串
b64 = Convert.ToBase64String(content);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return b64;
}
public static async Task Main(string[] args)
{
string url = "https://ocr-api.shiliuai.com/api/invoice_ocr/v1";// 请求接口
string appcode = "你的APPCODE";
string file_path = "本地文件路径";
// 设置请求头
Dictionary headers = new Dictionary
{
{ "Authorization", "APPCODE " + appcode }
// Content-Type 将在创建 StringContent 时设置
};
// 请求体
JObject requestObj = new JObject();
requestObj["file_base64"] = GetBase64(file_path);
string body = requestObj.ToString();
try
{
using (HttpClient client = new HttpClient())
{
// 设置请求头
foreach (var header in headers)
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
// 创建请求内容
StringContent content = new StringContent(body, Encoding.UTF8, "application/json");
// 发送请求并获取响应
HttpResponseMessage response = await client.PostAsync(url, content);
if (!response.IsSuccessStatusCode)
{
Console.WriteLine($"Http code: {(int)response.StatusCode}");
return;
}
// 读取响应内容
string responseContent = await response.Content.ReadAsStringAsync();
JObject resObj = JObject.Parse(responseContent);
Console.WriteLine(resObj.ToString(Formatting.Indented));
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
五、识别结果如何使用?
识别成功后,系统可以自动完成:
- 自动填充报销单
- 自动录入财务系统
- 自动归档发票数据
例如:
form.invoice_number = result.invoice_number
form.amount = result.total_amount
这样可以极大提升系统效率。
六、真实项目中的几个常见问题
在实际落地中,经常会遇到这些问题。
1️⃣ 发票图片不清晰
例如:
- 手机拍摄模糊
- 光线过暗
- 图片压缩严重
建议:
- 上传前压缩尺寸
- 保持图片清晰
2️⃣ 发票版式不同
不同发票类型包括:
- 增值税普通发票
- 增值税专用发票
- 电子发票
OCR 系统可以适配不同模板,基本全可以识别。
3️⃣ 批量处理需求
很多企业需要:
- 批量上传发票
- 自动识别
- 自动归档
因此接口稳定性和并发能力非常重要。
七、在线工具 vs API 接入
不同场景适合不同方案。
在线工具
适合:
- 临时识别
- 手动使用
- 少量图片
如果只是想快速测试效果,可以先在线识别一张发票看看(支持结构化导出发票内容为不同格式的文件,如ECXEL、WORD、PDF等)。
API 接入
适合:
- 企业系统
- 财务系统
- 报销平台
- 自动化流程
八、总结
发票 OCR 可以帮助企业实现:
- 自动识别发票信息
- 自动录入财务系统
- 提高数据处理效率
随着 OCR 技术成熟,现在通过 API 接入即可快速实现自动化能力。
如果你的系统涉及:
- 报销系统
- 财务系统
- ERP
- RPA 自动化
发票 OCR 都是一个非常值得接入的基础能力。