跳到主要内容
开发者指南

将 Tesseract 作为 API 运行
或作为自托管服务。

放心地将 Tesseract 封装为 HTTP 服务:生产级 FastAPI 端点、进程池并发、包含语言包和健康检查的 Docker 镜像、扩缩容与背压,以及无服务器部署——并对比托管 OCR API 的隐私与成本权衡。

TL;DR — 最小服务

将 CLI 或 pytesseract 绑定封装在 HTTP 之后。图像永远不会离开你的基础设施。

bash
pip install fastapi uvicorn python-multipart pytesseract pillow
# 先安装引擎 + 语言包(参见安装指南)
uvicorn app:app --host 0.0.0.0 --port 8000

然后调用:curl -F "file=@invoice.png" "http://localhost:8000/ocr?lang=chi_sim"。Tesseract 本身按安装指南安装。

先做设计决策

三个选择决定整个服务。

决策选项建议
同步 vs 异步阻塞请求 vs 任务队列单张图像几秒内用同步;大文档或批处理用异步任务 ID。
输入multipart 上传 vs base64 JSON二进制图像优先 multipart;仅当客户端无法上传文件时才用 base64(增加约 33% 体积)。
输出纯文本、JSON、hOCR/ALTO、可搜索 PDF默认返回 JSON;为版式提供 hOCR,为归档提供 PDF 下载 URL。

每个端点一个主要意图。/ocr 保持返回文本,为 PDF 和版式数据另设端点,而不是让一个响应过载。

生产级 Python 服务(FastAPI)

校验、大小限制、超时,以及让 OCR 离开事件循环。

app.py
import asyncio, io
from concurrent.futures import ProcessPoolExecutor
from fastapi import FastAPI, File, UploadFile, HTTPException, Query
from PIL import Image
import pytesseract

app = FastAPI(title="Tesseract OCR API")
pool = ProcessPoolExecutor(max_workers=4)
MAX_BYTES = 10 * 1024 * 1024  # 10 MB
LANGS = {"eng", "chi_sim"}

def _ocr(data: bytes, lang: str) -> str:
    image = Image.open(io.BytesIO(data))
    return pytesseract.image_to_string(image, lang=lang)

@app.get("/health")
def health():
    return {"status": "ok"}

@app.post("/ocr")
async def ocr(file: UploadFile = File(...), lang: str = Query("chi_sim")):
    if lang not in LANGS:
        raise HTTPException(400, "不支持的语言")
    data = await file.read()
    if len(data) > MAX_BYTES:
        raise HTTPException(413, "文件过大")
    loop = asyncio.get_running_loop()
    try:
        text = await asyncio.wait_for(loop.run_in_executor(pool, _ocr, data, lang), timeout=30)
    except asyncio.TimeoutError:
        raise HTTPException(504, "OCR 超时")
    return {"text": text, "lang": lang}

关键点:语言白名单,在解码之前强制字节上限,在进程池中运行 OCR,并限制实际耗时。完整的 pytesseract API 见 Python 指南。

容器化

将 Tesseract 和语言包烘焙进镜像,使副本完全一致。

Dockerfile
FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
      tesseract-ocr tesseract-ocr-eng tesseract-ocr-chi-sim \
      libgl1 libglib2.0-0 && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 8000
HEALTHCHECK CMD python -c "import urllib.request;urllib.request.urlopen('http://localhost:8000/health')"
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]

只添加需要的语言包以保持镜像精简。安装指南更详细地介绍了 Docker 和 tessdata 的放置。

并发与扩缩容

OCR 是 CPU 密集型——用进程而非线程并行。

安全与隐私

自托管是团队选择 Tesseract 的主要原因。

无服务器与容器平台

自托管 Tesseract vs 托管 OCR API

维度自托管 Tesseract托管 OCR API
成本固定基础设施;无按页费用按请求/页付费;随用量增长
隐私文档永不离开你的网络文档发送给第三方
精度清晰印刷体表现强;可按领域调优在困难扫描件和手写上往往更强
控制完全:版本、语言、自定义模型供应商路线图与配额
运维你负责:扩缩容、升级、监控完全托管

许多团队对大批量、隐私敏感的工作自托管 Tesseract,只对少数困难文档回退到托管 API。

API 常见问题

如何将 Tesseract OCR 作为 API 运行?

将 CLI 或 pytesseract 封装在 FastAPI/Flask 中,暴露 POST /ocr 并容器化。图像留在你的基础设施内。

用线程还是进程?

进程。OCR 是 CPU 密集型,GIL 阻碍线程并行;使用 ProcessPoolExecutor 或 CLI 子进程。

自托管 API 是否私密?

是:上传的图像在本地处理,绝不发送给第三方,不同于托管 OCR API。

能在无服务器上运行吗?

可以,在 Cloud Run、Lambda 容器镜像或 Fly.io 等容器平台上;注意冷启动和含语言包的镜像体积。

可以返回哪些格式?

纯文本、带置信度的 JSON、hOCR/ALTO,或通过下载 URL 提供的可搜索 PDF。