OCR It:面向LLM与RAG的PDF和截图文本提取工具实战
2026/9/17 13:38:31 网站建设 项目流程

这次我们来看一个很现实的场景:手头有一份 PDF,字看得见,但复制不出来;或者是一张截图,里面全是表格,想直接丢给 LLM 让它总结,结果模型要么读不到内容,要么回得七零八落。OCR It 要解决的就是这类问题——从无法复制的文档中提取文本,然后把结果变成 LLM 能直接吃掉的输入。

这个项目最值得关注的有三点:第一,面向扫描版 PDF、截图、图片这类“看得见但拿不到”的文本来源;第二,输出不只是纯文本,还能生成 Markdown 或结构化文本,方便直接塞进 LLM 上下文,或者喂给 RAG 管道;第三,部署方式灵活,既能本地离线跑,也能封装成接口服务,对已有工具链做集成。

如果你是做 LLM 应用开发的,你会发现大多数 RAG 项目卡在第一公里:让模型在读文档之前,先把文档里的字“拿出来”。OCR It 就是这一公里的解决方案。本文会带你把核心能力、环境准备、部署启动、功能测试、API 调用和批量任务整体过一遍,最后给一份常见问题排查清单。

1. OCR It 核心能力速览

从项目定位看,OCR It 是一个面向 LLM 数据预处理的文档文本提取工具。下面这张表先把关键规格列出来,方便你快速判断它适不适合自己的环境。

能力项说明
项目类型OCR 文档文本提取工具,面向 LLM 预处理场景
输入类型图片、扫描 PDF、不可复制的 PDF、截图
输出格式纯文本、Markdown、结构化文本(按实际版本确认)
识别引擎可选用 Tesseract、PaddleOCR、百度 OCR API 等方案
硬件门槛轻量 OCR 模型 CPU 可跑;GPU 可加速,显存占用与模型规模相关
启动方式命令行、Python 脚本、HTTP 服务
批量任务支持目录批量处理,建议自行设计队列与日志
API 集成可封装为接口供 LLM / RAG 调用
适合场景论文、合同、报表、聊天截图等 LLM 数据预处理

这里需要说明一点:不同的 OCR 引擎识别质量差异很大,建议先拿自己的真实文档打样,再决定用哪个方案。Tesseract 胜在免费轻量,PaddleOCR 胜在中文场景和排版还原,云端 API 胜在省事但要注意费用和合规。

2. 适用场景与使用边界

OCR It 能解决的问题很明确:内容看得见、但文本拿不出来的文档。典型场景包括:

  • 扫描版 PDF,整页都是图片,复制后全是空白。
  • 政府文件、合同扫描件、传真件,文字糊但不至于读不出来。
  • 网页长截图、聊天记录截图、会议白板照片。
  • PPT 导出成图片后,不能直接选中文本。
  • 加密 PDF 或选择不提供文本层的 PDF,无法直接复制。

这些材料如果要进入 LLM 的处理流程,必须先做 OCR。OCR It 的思路就是把这些材料统一转成“LLM 友好”的文本。

但也要说清楚边界。OCR 不是万能的,以下几类场景不建议硬上:

  • 手写体识别。除非专门训练过,否则通用 OCR 对手写体、花体字的识别率会明显下降。
  • 强调版式精确还原的文档。OCR 输出的是文本流和简单结构,不是 PDF 版式重现。
  • 涉及个人隐私、商业机密、版权内容的处理。需要先确认你有权使用这些材料。

合规问题必须放在前面:抓取他人网站内容做 OCR、识别未授权文档、处理包含个人信息的图片,都可能涉及版权和隐私风险。自用工具也建议只处理你有使用权的文件。

3. OCR It 本地部署环境准备

无论用哪种 OCR 引擎,环境准备的核心是四件事:Python 运行环境、OCR 引擎本体、模型或语言数据包、输出目录。

3.1 操作系统与 Python

Windows、Linux、macOS 都可以跑。建议使用 Python 3.10 或更高版本,并用虚拟环境隔离依赖,避免污染系统 Python。

# Linux / macOS python3 -m venv .venv source .venv/bin/activate # Windows PowerShell python -m venv .venv .venv\Scripts\activate

3.2 Tesseract 路线

Tesseract 是老牌 OCR 引擎,适合英文和文本结构简单的文档。Windows 用户需要下载 Tesseract 5 的 Windows 64 位安装包,安装时勾选需要的语言包,尤其是简体中文chi_sim

安装完成后,做两步检查:

tesseract --version echo %TESSDATA_PREFIX% # Windows

如果 TESSDATA_PREFIX 没有设置,识别中文时会报 “Failed loading language ‘chi_sim’”。可以把 Tesseract 安装目录下的tessdata路径加入环境变量。

3.3 PaddleOCR 路线

PaddleOCR 在中文场景里识别效果更稳,对表格、印章、倾斜文字的鲁棒性也更好。安装 PaddlePaddle 和 PaddleOCR:

pip install paddlepaddle paddleocr

如果你的机器有 NVIDIA GPU,并且确认 CUDA 环境正常,可以安装 GPU 版 PaddlePaddle:

pip install paddlepaddle-gpu

GPU 版具体安装命令会根据 CUDA 版本变化,建议到 PaddlePaddle 官方安装页复制对应的 wheel 地址。

3.4 百度 OCR API 路线

走 API 方案不需要本地模型。去百度智能云创建 OCR 应用,拿到 API Key 和 Secret Key,然后通过 Access Token 调用。

这里顺带回应一个搜索热词:“百度 OCR 怎么在 RK3588 运行”。要区分两种方式:

  • 如果你在 RK3588 上跑本地 OCR,比如 Tesseract 或 PaddleOCR,那是本地推理,关注的是 CPU/GPU/NPU 性能和推理框架的支持情况。
  • 如果你只是调用百度 OCR 的 HTTP API,那和芯片基本没关系,只要设备能联网发请求就能用。

很多嵌入式场景会混这两者。OCR It 的接口模式走的是后者,本地只负责发请求、收结果、整理文本。

4. OCR It 安装部署与启动方式

OCR It 的启动方式可以从简单到复杂分成三档:命令行、Python 脚本、HTTP 服务。先跑通最简单的,再决定要不要封装。

4.1 命令行快速识别

如果只是偶尔识别一两张图,Tesseract 命令行最直接:

tesseract data/sample.png output -l chi_sim+eng --psm 6

--psm 6表示把图片当成一个文本块处理,适合大部分截图。output是输出文件前缀,结果会保存为output.txt

PaddleOCR 也提供命令行入口,但不同版本的参数差异比较大。新版可以用:

paddleocr --image_dir data/sample.png --lang ch

如果命令报参数错误,优先看当前版本帮助:

paddleocr --help

4.2 Python 脚本调用

推荐用 Python 方式,因为后面无论是批量任务还是接入 LLM,都需要在代码里拿到 OCR 结果对象。

from paddleocr import PaddleOCR ocr = PaddleOCR( lang='ch', use_gpu=False, # 有 GPU 且安装 GPU 版时可以改成 True ocr_version='PP-OCRv4' # 以实际安装版本为准 ) result = ocr.predict('./data/sample.png') for line in result: texts = line.get('rec_texts', []) for text in texts: print(text)

跑通这段后,你就有了一个可控的 OCR 提取函数。后面所有批量任务、接口封装都可以围着这个函数展开。

4.3 HTTP 服务启动

如果要把 OCR 能力暴露给其他服务调用,最简单的方式是包一个 Flask 接口。下面是一个通用模板,端口和路由需要按实际项目调整:

# app.py from flask import Flask, request, jsonify from paddleocr import PaddleOCR app = Flask(__name__) ocr = PaddleOCR(lang='ch', use_gpu=False) @app.route('/ocr', methods=['POST']) def ocr_image(): if 'file' not in request.files: return jsonify({'error': 'no file'}), 400 file = request.files['file'] file.save('/tmp/ocr_input.png') result = ocr.predict('/tmp/ocr_input.png') texts = [] for line in result: texts.extend(line.get('rec_texts', [])) return jsonify({'texts': texts}) if __name__ == '__main__': app.run(host='127.0.0.1', port=8000)

启动:

python app.py

然后另开一个终端测试:

curl -X POST -F "file=@data/sample.png" http://127.0.0.1:8000/ocr

返回 JSON 包含识别出来的文本数组,这个接口就可以接入你现有的 LLM 应用了。

5. OCR It 功能测试与效果验证

部署完成不等于能直接用于生产。我建议按下面几个维度逐项验证,每个都记录结果,方便后续调优。

5.1 单张图片识别测试

测试目的:确认基础识别链路是否正常。

输入:一张包含中文和英文的截图。

curl -X POST -F "file=@data/sample.png" http://127.0.0.1:8000/ocr

预期结果:返回 JSON 中包含中文和英文文本,顺序与图片内容一致。

判断标准:文字没有大面积缺行、乱码,数字和字母没有明显串行。

常见失败:返回空数组,先检查图片是否太暗、太小;中文识别出乱码,优先检查语言包是否完整。

5.2 PDF 提取测试

PDF 无法直接 OCR,需要先把每一页渲染成图片,再走识别流程。用 pypdfium2 可以做这一层转换:

import pypdfium2 as pdfium from pathlib import Path pdf = pdfium.PdfDocument('data/demo.pdf') output_dir = Path('data/pages') output_dir.mkdir(exist_ok=True) for i in range(len(pdf)): page = pdf[i] bitmap = page.render(scale=2) # 2 倍分辨率,提升小字号文本识别率 img = bitmap.to_pil() img.save(output_dir / f'page_{i:03d}.png')

渲染完成后,把每张页面图循环送入 OCR。实际测试时,建议先取 2 到 3 页试跑,确认时间成本和识别质量,再处理整份文档。

5.3 表格和图文混排测试

表格是 OCR 最容易翻车的地方。常见问题是:多列表格被识别成一行,列与列之间无法区分。

Tesseract 有专门处理表格的--psm 6和 TSV 输出模式,但效果有限。PaddleOCR 对简单表格的识别更可靠。如果表格结构比较复杂,建议先做图像预处理,比如用 OpenCV 检测表格线、切分成单元格再逐一识别。

判断成功标准:表格数据每一列都能落到对应的文本字段里,而不是一行糊过去。如果这一步达不到要求,后续做 LLM 结构化分析会非常吃力。

5.4 Markdown 输出测试

LLM 友好的输出,Markdown 比纯文本更好。一个简单的策略:先用 OCR 得到文本块和坐标,然后按坐标做段落到 Markdown 的映射。

def to_markdown(result): lines = [] for line in result: texts = line.get('rec_texts', []) lines.extend(texts) return '\n\n'.join(lines)

这是最简版本。实际项目中可以根据坐标把标题、列表、表格分别标记,输出更规范的 Markdown。测试时用一个带标题和列表的文档,看看输出结构与原文差异有多大。

5.5 批量目录测试

批量任务最怕的是“跑了一半卡住”。建议先把批处理脚本写好,再加日志和失败重试。下面是一个可运行的目录遍历模板:

import pathlib from paddleocr import PaddleOCR image_dir = pathlib.Path('./inputs') output_dir = pathlib.Path('./outputs') output_dir.mkdir(exist_ok=True) ocr = PaddleOCR(lang='ch', use_gpu=False) for img_path in sorted(image_dir.glob('*.png')): try: result = ocr.predict(str(img_path)) texts = [] for line in result: texts.extend(line.get('rec_texts', [])) out_file = output_dir / f'{img_path.stem}.md' out_file.write_text('\n'.join(texts), encoding='utf-8') print(f'[OK] {img_path.name}') except Exception as exc: print(f'[FAIL] {img_path.name}: {exc}')

先放 3 到 5 张图跑一遍,确认输出文件完整,再放整个目录。

5.6 LLM 消费测试

OCR 文本最终要给 LLM 用。测试时把识别结果直接作为上下文发给 LLM,看是否可理解:

from openai import OpenAI client = OpenAI( base_url='http://127.0.0.1:8000/v1', # 本地 LLM 服务地址 api_key='not-needed', ) ocr_text = open('outputs/合同第一页.md', encoding='utf-8').read() resp = client.chat.completions.create( model='local-model', messages=[ {'role': 'system', 'content': '你是一个文档助理,请根据用户提供的 OCR 文本回答问题。'}, {'role': 'user', 'content': ocr_text + '\n\n请提取这份文档中的金额和日期。'} ] ) print(resp.choices[0].message.content)

如果这一步能稳定提取出金额、日期、甲方乙方名称,说明 OCR 质量足够支撑 LLM 的下游任务。

6. OCR It 接口 API 与批量任务设计

把 OCR 能力接口化之后,可以很方便地接进 LLM Agent、RAG 流程或自动化脚本。这里给出三套典型代码:本地 OCR 封装、百度 OCR API 调用、LLM 消费链路。

6.1 百度 OCR API 调用示例

使用云端 API 前需要准备 API Key 和 Secret Key:

import base64 import requests API_KEY = 'your_api_key' SECRET_KEY = 'your_secret_key' def get_access_token(): url = 'https://aip.baidubce.com/oauth/2.0/token' resp = requests.post(url, params={ 'grant_type': 'client_credentials', 'client_id': API_KEY, 'client_secret': SECRET_KEY, }) return resp.json().get('access_token') def ocr_by_api(image_path, access_token): with open(image_path, 'rb') as f: image_data = base64.b64encode(f.read()).decode() url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic' resp = requests.post(url, params={'access_token': access_token}, data={ 'image': image_data, }) words = [item['words'] for item in resp.json().get('words_result', [])] return '\n'.join(words) token = get_access_token() print(ocr_by_api('data/contract.jpg', token))

云端 API 的好处是本地不需要装 OCR 模型,网络请求返回结构化文本;坏处是费用、请求频率限制,以及图片内容会经过第三方服务。敏感数据要谨慎使用。

6.2 批量任务队列设计

批量处理的工程化建议是:输入目录、输出目录、日志目录三分离。每次处理都记录文件状态,避免重复处理和中断后重新开始。

import json import pathlib input_dir = pathlib.Path('./inputs') output_dir = pathlib.Path('./outputs') state_file = pathlib.Path('./tasks.json') if state_file.exists(): tasks = json.loads(state_file.read_text(encoding='utf-8')) else: tasks = {p.name: 'pending' for p in input_dir.glob('*.png')} for name, status in tasks.items(): if status == 'done': continue try: # 执行 OCR 并保存结果 tasks[name] = 'done' except Exception as exc: tasks[name] = f'error: {exc}' state_file.write_text( json.dumps(tasks, ensure_ascii=False, indent=2), encoding='utf-8' )

通过 state 文件记录状态,进程中断后重启可以跳过已完成任务,只处理失败和未开始的文件。

6.3 OCR It 接入 LLM 的完整链路

一个典型的“OCR + LLM”管道有三步:识别、清洗、交给 LLM。识别得到文本后,先处理掉 OCR 常见的噪声,比如多余空格、页脚、页码:

import re def clean_ocr_text(text): text = re.sub(r'\s+', ' ', text) text = re.sub(r'第\s*\d+\s*页', '', text) return text.strip()

清洗后的文本再交给 LLM。如果文本过长,先做 chunk 切分,按段落分块,避免超过 LLM 上下文窗口。

7. OCR It 资源占用与性能观察

OCR It 的资源占用取决于选择哪个引擎、跑在什么硬件上。这里给一套观察方法,具体数字要以本机测试为准。

  • 显存观察:Windows 用任务管理器,Linux 用nvidia-smi -l 1,重点看 OCR 进程占用。
  • 模型加载时机:PaddleOCR 首次调用需要加载模型,启动阶段耗时明显,后续单张图片处理更快。生产环境建议服务启动后就预热模型。
  • CPU 推理:PP-OCR mobile 这类轻量模型在 CPU 上可跑,速度取决于图片尺寸和 CPU 核数。处理 1080P 截图时,单张可能在 1 到 3 秒之间,具体以实测为准。
  • GPU 推理:显存占用与模型大小、批量大小、图片分辨率相关。如果显存不够,把批量数降到 1,或者换更小的模型。
  • 内存:处理大 PDF 时分页渲染再识别,避免整份文档一次性加载到内存。

降低资源占用的几个实用技巧:

  • 图片预处理:灰度化、二值化、去噪。
  • 适当降低渲染分辨率,非关键页面可以scale=1而不是scale=2
  • 限制 OCR 多线程数量,避免多个任务同时跑导致内存峰值过高。
  • 批量任务控制在 2 到 4 个并发,优先保证稳定而不是速度。

8. OCR It 常见问题与排查方法

问题现象可能原因排查方式解决方案
中文识别出一堆乱码语言包缺失或未设置 TESSDATA_PREFIX查看 tesseract 日志安装 chi_sim 语言包并配置环境变量
PaddleOCR 下载模型失败网络问题或模型地址变更查看模型缓存目录手动下载模型文件放到缓存目录
PaddlePaddle 安装失败Python 版本或 CUDA 不匹配检查 Python 版本和 CUDA 版本按官网 wheel 表选择对应版本
GPU 跑不起来,总是 CPU 在算安装的是 CPU 版 PaddlePaddle打印 paddle 版本信息安装 paddlepaddle-gpu
OCR 返回空数组图片太暗、太小或压缩过度打开图片检查质量提高分辨率,做图像增强
大 PDF 处理内存溢出一次性加载所有页面观察内存占用曲线分页渲染后再逐页识别
OCR 文本串行、表格错乱表格线干扰识别检查原图表格结构先做表格线检测和单元格切割
接口服务启动后访问不到端口被占用或服务未启动检查日志和端口监听更换端口或重启服务
LLM 上下文超长OCR 文本未做切分查看单次文本 token 数按段落切分,分块调用
批量任务中途卡住单张图片耗时过长或死锁查看任务状态文件加超时控制,记录失败原因后继续

排查原则很朴素:先看日志,再看状态文件,最后看资源占用。不要一上来就重启服务,先确定是哪个环节卡住了。

9. OCR It 最佳实践与使用建议

从工程化角度,以下几个建议能明显减少踩坑次数。

第一,第一次使用不要直接跑全量。先拿 5 到 10 张有代表性的图片做验证,确认识别质量和速度满足需求,再上批量。

第二,保留一套最小可运行配置。不管是命令行还是 Python 脚本,把环境依赖和启动命令写进 README,换机器时能快速复现。

第三,目录分开管理。输入文件、输出文件、模型缓存、日志目录不要混在一起。批量任务一定要加任务状态文件。

第四,OCR 文本必须做后处理清洗。页脚、页码、多余空行都是噪声,直接给 LLM 会浪费 token 并影响效果。

第五,接口服务要限制访问范围。启动时绑定127.0.0.1,不要无脑绑到0.0.0.0。如果有多台机器需要访问,再加认证层。

第六,涉及人脸、签名、身份证、合同金额等敏感信息时,先确认你是否有权处理。本地 OCR 比云端 API 更可控,但同样要注意数据安全。

第七,LLM 输出的结果要复核。OCR 识别错误会传递到 LLM 的最终答案中,尤其是金额、日期、编号这类关键字段,建议加一道规则校验。

10. 总结与下一步

OCR It 最值得尝试的点,是把“看得见但拿不到”的文档文本快速变成 LLM 可消费的输入。整个链路并不复杂:图片或 PDF 进入 OCR 引擎,得到文本,清洗后交给 LLM。真正决定效果的不是选哪个框架,而是你对输入质量的管控和输出文本的清洗程度。

拿到项目后,建议最先验证三件事:一张中文截图能不能正确识别、扫描版 PDF 能否分页提取、识别结果丢给 LLM 后能不能稳定抽取关键字段。这三项跑通,项目就已经能用起来了。

最容易踩的坑集中在两个地方:一是语言包和模型文件没下全,二是批量任务缺少状态管理。前者会导致乱码或空输出,后者会让长任务中断后无从下手。

后续可以扩展的方向很多:把 OCR 结果接入 RAG 做知识库问答、用视觉大模型对复杂版面做二次理解、把批量任务改成异步队列,甚至加一个 WebUI 让非技术同学直接上传文件拿结果。先把 OCR 到 LLM 这条主链路跑稳,后面的想象空间会很大。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询