用 EasyOCR 搭建 LiteParse 独立 OCR 服务:部署、HTTP API 与接入实战
【免费下载链接】liteparseA fast, helpful, and open-source document parser项目地址: https://gitcode.com/GitHub_Trending/li/liteparse
LiteParse 除了内置的 Tesseract OCR 之外,还支持通过标准 HTTP 接口挂载外部 OCR 引擎,ocr/easyocr/目录下的 EasyOCR 服务就是一个官方提供的参考实现:一个封装 EasyOCR 库、遵循 LiteParse OCR API 规范的 HTTP 服务。读完本文,你将掌握如何用uv一键启动该服务、理解其POST /ocr接口的请求/响应协议与源码实现细节,并能通过 CLI 或编程方式让 LiteParse 使用 EasyOCR 解析扫描版 PDF 与图片文档。
EasyOCR 服务在 LiteParse 生态中的定位
EasyOCR 服务本质上是一个"桥接器"。它并不参与 LiteParse 的文档版面分析、阅读顺序重建等流程,只负责做一件事:接收一张图片,返回识别出的文字及其位置信息。只要返回格式符合 OCR API 规范,LiteParse 就可以在任何 OCR 引擎(EasyOCR、PaddleOCR、Surya,甚至云 API)之间无缝切换。
在 ocr/ 目录总览 中,官方把内置 Tesseract.js 与三个外部 OCR 服务做了横向对比:
| 维度 | Tesseract.js(内置) | EasyOCR | PaddleOCR | Surya |
|---|---|---|---|---|
| 安装成本 | 零(随 LiteParse 内置) | uv | uv | uv |
| 速度 | 中等 | 中等 | 快(约 2-3 倍) | 中等(建议 GPU) |
| 拉丁文精度 | 良好 | 良好 | 良好 | 优秀 |
| 中日韩(CJK)精度 | 一般 | 良好 | 优秀 | 优秀 |
| 支持语言 | 100+ | 80+ | 80+ | 91 |
| 运行形态 | 进程内 | 独立服务 | 独立服务 | 独立服务 |
EasyOCR 的定位是"综合平衡":无需 GPU、支持 80+ 语言、拉丁文与 CJK 都有可用精度,适合作为通用场景的默认外部 OCR。服务的默认端口是8828。
一键构建与启动:uv run server.py
EasyOCR 服务的依赖管理使用 uv 中声明了全部依赖:
easyocr>=1.7.2:OCR 引擎本体;fastapi>=0.132.0:Web 框架,提供路由与参数校验;uvicorn>=0.41.0:ASGI 服务器;numpy>=2.4.2与pillow>=12.2.0:图像解码与数组转换;python-multipart>=0.0.31:解析multipart/form-data上传;- 开发依赖:
pytest>=9.0.3、httpx>=0.28.1(供测试使用)。
启动只需一条命令:
# 在 ocr/easyocr 目录下执行 uv run server.pyuv run会自动创建虚拟环境并同步依赖。服务启动后监听0.0.0.0:8828,对应源码 server.py 中的uvicorn.run(app, host="0.0.0.0", port=8828)。
需要注意的是:EasyOCR 首次运行某个语言时会自动下载对应的检测与识别模型权重(由easyocr.Reader([language], gpu=False)触发),因此第一次请求可能较慢,属正常现象。源码默认使用gpu=False,即纯 CPU 推理,无需 CUDA 环境即可运行。
Docker 部署
仓库同时提供了 Dockerfile,便于在生产或隔离环境中部署:
FROM ghcr.io/astral-sh/uv:python3.12-trixie # 安装 OpenCV/EasyOCR 所需的系统库:libgomp1、libglib2.0-0、libsm6、libxext6、libxrender-dev、libgl1 WORKDIR /app COPY ./*py* . RUN uv sync EXPOSE 8828 CMD ["uv", "run", "python3", "server.py"]构建后暴露 8828 端口,与裸机启动行为一致。官方提供的libgomp1、libgl1等系统依赖是 EasyOCR 底层 OpenCV 在 Debian 系镜像中的必要运行库,直接照搬可避免"缺库启动失败"的常见坑。
HTTP API 协议:POST /ocr
服务只暴露一个核心端点,其协议与 LiteParse 侧的期望完全对齐(见 OCR API 规范):
- 端点:
POST /ocr - Content-Type:
multipart/form-data - 请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | 二进制 | 是 | 图片文件(PNG、JPG 等) |
language | 字符串 | 否 | 语言代码,默认en |
一个完整的 curl 调用示例:
curl -X POST -F "file=@image.png" -F "language=en" http://localhost:8828/ocr响应格式
{ "results": [ { "text": "recognized text", "bbox": [x1, y1, x2, y2], "confidence": 0.95 } ] }其中bbox是轴对齐包围盒[x1, y1, x2, y2]:(x1, y1)为左上角、(x2, y2)为右下角,坐标原点在图片左上角、单位为像素,且满足x2 > x1、y2 > y1;confidence为归一化到 0.0~1.0 的置信度。规范还鼓励在检测到旋转文本时额外返回可选的polygon字段(4 点多边形,按"字形正立阅读方向"的左上→右上→右下→左下排序),LiteParse 会利用它识别竖排/侧向文字(如法律文书的侧边栏)并路由到旋转阅读顺序处理器。
源码视角:EasyOCR 结果如何变成标准格式
EasyOCR 的readtext()返回的是三元组列表:[[[x1,y1],[x2,y2],[x3,y3],[x4,y4]], text, confidence],即"多边形 + 文本 + 置信度"。服务端在 server.py 中做了两步转换:
- 多边形 → 轴对齐包围盒:取 4 个点的
min/max得到bbox;同时用int()显式转换坐标,因为np.Int32无法被 pydantic 序列化(源码注释明确指出了这一点); - 语言代码归一化:通过
LANG_MAP = {"eng": "en"}把 EasyOCR 使用的 Tesseract 风格代码eng映射为规范约定的 ISO 639-1 代码en;请求中的语言先统一lower(),再按映射归一。
另外,服务端实现了Reader 缓存:if self.reader is None or self.current_language != language时才重新初始化easyocr.Reader,同一语言的连续请求会复用已加载的模型,避免每次请求都重新加载权重(这也符合 OCR API 规范 中"在内存中缓存 OCR 模型"的性能建议)。服务还额外实现了GET /health健康检查端点,返回{"status": "healthy"},便于负载均衡与监控探活。
支持的语言
EasyOCR 支持 80+ 种语言。常用语言代码如下:
en- 英语fr- 法语de- 德语es- 西班牙语zh- 中文ja- 日语ko- 韩语ar- 阿拉伯语
完整语言列表以 EasyOCR 官方文档为准(README 中给出了官方语言表链接)。注意:EasyOCR 内部语言代码与 LiteParse CLI 默认的 Tesseract 风格代码存在差异(如 Tesseract 的eng对应 ISO 的en),这正是服务端LANG_MAP归一化逻辑存在的意义——调用方统一使用 ISO 639-1 代码,映射工作由服务端完成。
接入 LiteParse:CLI 与编程两种方式
服务启动后,即可让 LiteParse 用它替换内置 OCR。
方式一:CLI(lit parse)
# 使用 EasyOCR 解析文档 lit parse document.pdf --ocr-server-url http://localhost:8828/ocr # 指定识别语言(中文) lit parse document.pdf --ocr-server-url http://localhost:8828/ocr --ocr-language zhCLI 相关参数完整说明见 CLI 参考文档:
| 参数 | 说明 | 默认值 |
|---|---|---|
--no-ocr | 完全禁用 OCR | — |
--ocr-language <lang> | OCR 语言代码 | eng |
--ocr-server-url <url> | HTTP OCR 服务器 URL | —(使用内置 Tesseract) |
--ocr-server-header <header> | 附加 HTTP 头,格式"Name: Value",可重复指定 | — |
--ocr-server-header特别适合带鉴权的内网服务,例如:
lit parse scan.pdf --ocr-server-url https://ocr.internal/ocr \ --ocr-server-header "Authorization: Bearer $TOKEN"这些参数最终落在 config.rs 的OcrOptions相关字段(如ocr_language默认"eng"、ocr_server_url: Option<String>、可重复的ocr_server_headers),并组装成 Rust 侧的HttpOcrEngine。
方式二:编程接口(TypeScript)
import { LiteParse } from 'liteparse'; const parser = new LiteParse({ ocrServerUrl: 'http://localhost:8828/ocr', ocrLanguage: 'en', }); const result = await parser.parse('document.pdf');Node 侧封装的完整字段定义可在 packages/node/src/lib.ts 与 packages/node/native.d.ts 中查看,Python 侧对应参数见 packages/python/liteparse/types.py。
底层调用链:LiteParse 如何消费这个服务
从源码结构看,LiteParse 与 EasyOCR 服务的交互由 crates/liteparse/src/ocr/http_simple.rs 中的HttpOcrEngine负责,核心流程是:
- 将页面的原始 RGB 像素数据编码为 PNG(
image::RgbImage→write_to(..., ImageFormat::Png)); - 以
multipart/form-data发送file(文件名固定image.png)与language字段; - 解析响应 JSON。客户端支持两种响应形态(
#[serde(untagged)]):标准形态{"results": [{text, bbox, confidence, polygon?}]},以及兼容生产环境的{"result": [[polygon, text, confidence], ...]}元组形态; - 对元组形态同样做"多边形 → 轴对齐 bbox"的换算,且仅当多边形恰好为 4 点时透传
polygon供投影器恢复旋转文本方向。
值得注意的是内置了相当健壮的重试与退避策略(OcrRetryConfig):默认最多 10 次尝试、基础退避 1s 翻倍并封顶 10s、附加最多 500ms 抖动以避免并发页面在服务恢复瞬间形成"惊群";连接中断走 500ms 快速重试;408/425/429/500/502/503/504等状态码视为可重试,而 4xx 确定性问题直接失败。LITEPARSE_DEBUG_OCR环境变量可开启请求级调试日志。这些逻辑都有对应的单元测试(test_response_deserializes、test_recognize_network_error、test_hedged_all_fails_returns_error等)验证。
测试:修改服务后如何回归
仓库为 EasyOCR 服务提供了 test_server.py,覆盖三个关键行为:
- 初始化状态:
EasyOCRServer初始时reader与current_language均为空; - 健康检查:
GET /health返回 200 与{"status": "healthy"}; - OCR 端点:用
MockEasyOCRReader伪造 EasyOCR 返回的三元组结果,验证服务端正确转换成{text, bbox, confidence}标准格式(含坐标min/max换算)。
运行测试:
uv run pytest test_server.py如果你修改了服务端逻辑(例如调整语言映射、改变 bbox 换算规则),应同步更新测试用例中的MockEasyOCRReader期望值,保持对规范的合规性。
接入后的验证与排障要点
启动服务并接入 LiteParse 后,可按以下顺序自查:
- 探活:
curl http://localhost:8828/health应返回{"status": "healthy"}; - 单图直连:用文中的 curl 示例直接调
POST /ocr,确认results数组与bbox、confidence字段完整; - 端到端:
lit parse document.pdf --ocr-server-url http://localhost:8828/ocr,观察是否正常产出文本; - 语言不符:确认 CLI/代码中传的
language是 ISO 639-1 代码(如en、zh),eng等 Tesseract 风格代码会被服务端映射,但映射表目前仅含eng→en一项,其余语言代码需确保 EasyOCR 原生支持; - 性能:规范建议单张图片处理时间控制在 10 秒内,并支持并发请求。EasyOCR 服务端已实现 Reader 复用,但 CPU 推理在密集场景下仍是瓶颈,必要时可通过 Docker 部署在带 GPU 的机器上(将源码中
gpu=False调整为gpu=True并安装对应 CUDA 版 PyTorch 即可)。
小结
ocr/easyocr/是理解 LiteParse 外部 OCR 扩展机制的最佳起点:它用不到一百行代码,把 EasyOCR 的"多边形 + 文本 + 置信度"输出翻译成 LiteParse 的标准{text, bbox, confidence}结构,并通过POST /ocr一个端点完成整条链路。掌握它的部署、协议与接入方式后,你既可以立即用--ocr-server-url提升扫描文档的解析质量,也可以照葫芦画瓢,为其他 OCR 引擎(参见 paddleocr/、suryaocr/ 两个同类实现)编写符合 OCR API 规范 的自定义服务。
【免费下载链接】liteparseA fast, helpful, and open-source document parser项目地址: https://gitcode.com/GitHub_Trending/li/liteparse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考