技术博客
票据/文档电子化:如何用印刷体OCR识别批量处理图片?

票据/文档电子化:如何用印刷体OCR识别批量处理图片?

作者: 万维易源
2026-09-01
印刷体OCR批量处理文档电子化并发
# 票据/文档电子化:如何用印刷体OCR识别批量处理图片? > 接口 926(接入点 926-1) · 免费 · POST/GET · JSON · 适用人群:文档电子化/档案/财务系统开发者 · 阅读时间:约 7 分钟 ## 核心要点 - 接口**没有原生批量能力**(文档未提供一次传多张图的批量接口或订阅推送)。 - 批量 = 业务侧「循环调用 + 并发控制(≤10)+ 失败重试/落库」。 - 配合图片预处理(缩放、压缩)与结果缓存,可在免费档位内稳定完成大批量电子化。 ## Why:批量电子化是真实刚需 财务要把几百张发票录进系统、档案室要把堆积的扫描件转成可检索文字——一张张点太慢。但本接口是单图请求-响应模型,批量只能由你的程序来编排。本文给出可落地的批量模式。 ## What:能力边界(先讲清,避免误用) | 能力 | 是否提供 | 说明 | |------|---------|------| | 单次多图批量 | ❌ 文档未提供 | 一次请求只处理一张图 | | 订阅/推送回调 | ❌ 文档未提供 | 无异步订阅模型 | | 单图同步识别 | ✅ | POST 一张图,同步返回结果 | 所以「批量」是**业务侧循环**,不是接口特性。不要期待一个参数传多张。 ## How:批量处理模式(Python) ```python import os, time, base64, requests from concurrent.futures import ThreadPoolExecutor APPKEY = "YOUR_APPKEY" ENDPOINT = "https://route.showapi.com/926-1" MAX_WORKERS = 8 # 低于并发上限 10 def ocr_file(path: str) -> dict: with open(path, "rb") as f: b64 = base64.b64encode(f.read()).decode("utf-8") for attempt in range(3): try: r = requests.post(ENDPOINT, params={"appKey": APPKEY}, data={"img_base64": b64, "need_all_region": "1"}, timeout=10) rb = r.json()["showapi_res_body"] if rb["ret_code"] == 0: return {"file": path, "ok": True, "text": rb.get("list") or rb.get("str")} if rb["ret_code"] in (80, 90): time.sleep(0.5 * (2 ** attempt)); continue return {"file": path, "ok": False, "ret_code": rb["ret_code"]} except requests.RequestException: time.sleep(0.5 * (2 ** attempt)) return {"file": path, "ok": False, "ret_code": "timeout"} folder = "./scans" files = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith((".png", ".jpg", ".jpeg"))] with ThreadPoolExecutor(max_workers=MAX_WORKERS) as ex: results = list(ex.map(ocr_file, files)) # 落库/写文件:results 中 ok=False 的进入人工队列 failed = [r for r in results if not r["ok"]] print(f"成功 {len(results)-len(failed)}/{len(results)},失败 {len(failed)}") ``` **Node.js(fetch + 简易并发信号量)** ```javascript const ENDPOINT = "https://route.showapi.com/926-1?appKey=YOUR_APPKEY"; async function ocrFile(path) { const b64 = require("fs").readFileSync(path).toString("base64"); const res = await fetch(ENDPOINT, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ img_base64: b64, need_all_region: "1" }), }); const rb = (await res.json()).showapi_res_body; return rb.ret_code === 0 ? { file: path, ok: true, text: rb.list || rb.str } : { file: path, ok: false }; } // 用并发信号量(参见《10 并发与档位优化》)控制同时最多 8 个 ``` **cURL 批量(shell 循环,单并发)** ```bash for f in scans/*.png; do B64=$(base64 -w0 "$f") curl -s -X POST "https://route.showapi.com/926-1?appKey=YOUR_APPKEY" \ -H "content-type: application/x-www-form-urlencoded" \ --data-urlencode "img_base64=$B64" --data-urlencode "need_all_region=1" echo done ``` ## 返回示例与解析 与单图一致:成功 `ret_code=0`,取 `list`/`str`;失败按 `ret_code` 分类(见错误码篇)。 ## 批量工程化建议 | 环节 | 做法 | |------|------| | 预处理 | 批量前统一缩放 < 1200×1200、压缩至大小上限内,减少 `50/60/80` | | 并发 | 线程/协程池控制在 ≤8,远离并发上限 10 | | 重试 | `80/90` 指数退避;其他错误直接进失败队列,不盲目重试 | | 落库 | 成功结果写数据库/ES 供检索;失败项留人工队列 | | 缓存 | 同一文件 hash 命中则跳过调用,省额度(仅针对不变文件) | ## 进阶 / 边界 - **不是接口批量**:再次强调,批量是循环调用,接口一次只认一张图。 - **免费档位额度**:高量场景关注官方档位说明,必要时用积分兑换更高档位;架构上用缓存+预处理降量。 - **敏感票据**:发票/证件含个人信息,注意传输与存储合规,不要明文落库。 ## FAQ **Q1:能不能一次传一个 ZIP 或多张图?** A1:文档未提供该能力;当前只能逐张调用。如有此类需求需业务侧自行拆包后循环。 **Q2:批量会触发限流吗?** A2:并发超 10 易 `80 超时`;用并发池(≤8)+ 退避即可稳定。档位额度另见官方说明。 **Q3:几千张图要跑多久?** A3:取决于单图耗时与并发;按 8 并发、单张 ~0.5s 估算约 60~70 张/分,几千张约一小时级,请以实测为准(不编造精确值)。 **Q4:失败的任务会丢失吗?** A4:不会,只要落库失败队列;建议把 `ret_code` 与文件路径一起记录便于重试。 ## 相关能力 / 下一步阅读 - [免费接口也限流:印刷体OCR识别的 10 并发与档位优化指南](https://www.showapi.com/guides/printed-ocr-limit-cost-926) - [印刷体OCR识别错误码排查:10 参数错误到 90 识别异常逐条对照](https://www.showapi.com/guides/printed-ocr-error-handling-926) - [客服/审核后台赋能:一键识别用户上传图片中的文字](https://www.showapi.com/guides/printed-ocr-cs-empower-926) - **本系列共 12 篇**:查看[印刷体OCR识别指南总目录](https://www.showapi.com/guides/printed-ocr-guides-926)