从图片到JSON:利用DeepSeek-OCR-WEBUI实现表格数据自动提取
在日常办公和企业系统中,我们经常需要处理各种纸质单据、发票、采购表等包含结构化信息的图像文件。传统的人工录入方式不仅效率低,还容易出错。有没有一种方法,可以让我们“拍个照”,就能把表格内容自动转成可编辑、可存储的结构化数据?答案是肯定的。
本文将带你使用DeepSeek-OCR-WEBUI这款基于国产大模型的高性能OCR工具,完成从“图片”到“JSON”的全流程自动化提取。我们将重点解决一个实际问题:如何识别一张采购单上的表格,并将其转换为后端可用的JSON格式,供业务系统直接调用。
整个过程无需手动标注、不依赖复杂配置,只需部署一次服务,后续即可通过API批量处理大量图像文档。无论你是开发者、数据工程师,还是想提升办公效率的业务人员,都能从中获得实用价值。
1. 为什么选择 DeepSeek-OCR-WEBUI?
市面上的OCR工具不少,但大多数对中文表格的支持并不理想——要么识别不准,要么无法保留原始布局,更别说输出结构化数据了。而DeepSeek-OCR-WEBUI的出现,改变了这一局面。
它基于深度学习架构,融合了CNN与注意力机制,专为复杂场景设计,具备以下核心优势:
- 高精度中文识别:针对汉字优化,在模糊、倾斜、低分辨率图像中仍能保持高准确率。
- 多模式识别支持:提供
document、ocr、figure等多种识别模式,其中figure模式特别适合解析图表和表格。 - 结构化输出能力:不仅能提取文字,还能还原表格结构,返回HTML格式的表格代码,便于进一步解析。
- 轻量易部署:支持Docker一键部署,可在本地或服务器快速启动Web服务。
- 开放API接口:提供标准HTTP接口,方便集成到SpringBoot、Flask、Node.js等各类应用中。
更重要的是,它是国产自研技术,在中文语境下的表现远超许多国际主流OCR方案。
2. 环境准备与服务部署
要实现图片到JSON的转换,第一步是让OCR引擎跑起来。以下是完整的部署流程。
2.1 部署 DeepSeek-OCR-WEBUI 服务
确保你有一台配备NVIDIA显卡(如4090D)的机器,并已安装Docker和docker-compose。
# 克隆项目仓库 cd ~ git clone https://github.com/deepseek-ai/DeepSeek-OCR-WebUI.git cd DeepSeek-OCR-WebUI # 启动服务(使用Docker Compose) docker compose up -d启动后,可以通过日志查看运行状态:
docker logs -f deepseek-ocr-webui当看到类似Uvicorn running on http://0.0.0.0:8080的提示时,说明服务已经就绪。
访问http://你的IP:8080即可进入Web界面,也可以直接调用其提供的API接口。
注意:首次启动可能需要下载模型权重,耗时几分钟,请耐心等待。
3. 接口详解:如何识别表格?
DeepSeek-OCR-WEBUI 提供了一个简洁而强大的/ocr接口,支持上传图片并返回识别结果。我们要实现表格提取,关键在于正确使用参数。
3.1 API 接口定义
@app.post("/ocr") async def ocr_endpoint( file: UploadFile = File(...), prompt_type: str = Form("document"), find_term: str = Form(""), custom_prompt: str = Form(""), grounding: bool = Form(False) ):其中最重要的参数是prompt_type,它的取值决定了识别行为:
| 类型 | 说明 | 适用场景 |
|---|---|---|
document | 转Markdown,保留排版 | 合同、报告 |
ocr | 通用文字提取 | 图片转文本 |
free | 纯文本提取 | 快速读取内容 |
figure | 图表/表格解析 | 本文重点 |
describe | 图像描述生成 | 图片理解 |
find | 定位特定字段 | 发票信息查找 |
freeform | 自定义提示词 | 灵活任务 |
为了准确提取表格,我们必须设置prompt_type=figure。
3.2 测试接口调用
你可以用curl命令测试一下:
curl -X POST "http://localhost:8080/ocr" \ -F "file=@voucher.jpg" \ -F "prompt_type=figure" \ -H "Accept: application/json"如果一切正常,你会收到一段HTML格式的表格代码,例如:
<table> <tr><td>序号</td><td>条码</td><td>名称</td>...</tr> <tr><td>1</td><td>6949123352617</td><td>飞科PR-5261毛球修剪器</td>...</tr> ... </table>这正是我们需要的结构化起点。
4. SpringBoot 应用集成:从HTML到JSON
光有HTML还不够,我们的目标是把它变成JSON,这样才能被前端或其他系统消费。接下来,我们在SpringBoot项目中实现这一转换。
4.1 创建 OcrService 接口
首先定义一个服务接口,用于处理OCR识别逻辑:
// src/main/java/com/example/service/OcrService.java public interface OcrService { /** * 识别表格图片并返回结构化数据 * * @param file 上传的包含表格的图片文件 * @return 包含表格数据的Map对象,将以JSON格式返回给前端 */ Map<String, Object> recognitionTable(MultipartFile file); }4.2 实现 OCR 调用与解析
创建具体实现类DeepSeekOcrService,完成以下三步:
- 将图片上传至 DeepSeek-OCR-WEBUI
- 获取返回的HTML表格字符串
- 解析HTML为JSON结构
// src/main/java/com/example/service/DeepSeekOcrService.java @Service @Slf4j public class DeepSeekOcrService implements OcrService { private static final String OCR_URL = "http://localhost:8080/ocr"; @Override public Map<String, Object> recognitionTable(MultipartFile file) { log.info("开始识别表格,文件名:{}", file.getOriginalFilename()); try { RestTemplate restTemplate = new RestTemplate(); // 构建请求体:multipart/form-data LinkedMultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>(); requestBody.add("file", new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { return file.getOriginalFilename(); } }); requestBody.add("prompt_type", "figure"); // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); // 发送POST请求 HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers); ResponseEntity<String> response = restTemplate.postForEntity(OCR_URL, requestEntity, String.class); if (response.getStatusCode().is2xxSuccessful()) { String htmlContent = response.getBody(); return parseHtmlTableToJSON(htmlContent); } else { log.error("OCR识别失败,HTTP状态码:{}", response.getStatusCode()); throw new RuntimeException("OCR识别失败"); } } catch (Exception e) { log.error("处理文件时发生异常", e); throw new RuntimeException("文件处理失败:" + e.getMessage(), e); } } /** * 将HTML表格解析为JSON格式 * * @param html 包含<table>标签的HTML字符串 * @return 转换后的JSON数据,包含表头和行数据 */ private Map<String, Object> parseHtmlTableToJSON(String html) { Document doc = Jsoup.parse(html); Element table = doc.selectFirst("table"); List<Map<String, String>> rows = new ArrayList<>(); if (table == null) { throw new IllegalArgumentException("未找到表格元素"); } Elements trs = table.select("tr"); boolean isFirstRow = true; List<String> headers = new ArrayList<>(); for (Element tr : trs) { Elements tds = tr.select("td"); Map<String, String> row = new HashMap<>(); for (int i = 0; i < tds.size(); i++) { String text = tds.get(i).text().trim(); if (isFirstRow) { headers.add("col_" + i); // 默认列名 if (!text.isEmpty()) { headers.set(i, text); // 使用第一行作为表头 } } else { String key = i < headers.size() ? headers.get(i) : "col_" + i; row.put(key, text); } } if (!isFirstRow) { rows.add(row); } isFirstRow = false; } Map<String, Object> result = new HashMap<>(); result.put("headers", headers); result.put("data", rows); result.put("totalRows", rows.size()); return result; } }技术说明:
- 使用
RestTemplate发起HTTP请求- 利用
Jsoup解析HTML表格,提取行列结构- 第一行作为表头,后续每行对应一条记录
- 返回标准Map结构,SpringBoot会自动序列化为JSON
5. 添加控制器暴露API接口
为了让前端能够调用,我们需要添加一个REST控制器。
// src/main/java/com/example/controller/OcrController.java @RestController @RequestMapping("/api/ocr") @Slf4j public class OcrController { @Autowired private OcrService ocrService; @PostMapping("/process") public Map<String, Object> processFile(@RequestParam("file") MultipartFile file) { Map<String, Object> result = ocrService.recognitionTable(file); log.info("OCR识别结果: {}", JSON.toJSONString(result)); return result; } }现在你可以通过POST /api/ocr/process上传图片,系统会自动完成识别并返回JSON数据。
6. 编写测试用例验证功能
在正式上线前,先写个单元测试验证流程是否通畅。
// src/test/java/com/example/service/OcrServiceTest.java @SpringBootTest @Slf4j public class OcrServiceTest { @Autowired private OcrService ocrService; @Test void testRecognitionTableSuccess() throws Exception { // 加载测试图片 ClassPathResource resource = new ClassPathResource("voucher.jpg"); MockMultipartFile file = new MockMultipartFile( "file", "voucher.jpg", "image/jpeg", resource.getInputStream() ); // 调用服务 Map<String, Object> result = ocrService.recognitionTable(file); // 输出结果 log.info("OCR识别结果: {}", JSON.toJSONString(result)); // 断言非空 assertNotNull(result); assertTrue((Integer) result.get("totalRows") > 0); } }运行测试,若控制台打印出清晰的JSON结构,说明集成成功!
7. 前后端联调:构建完整工作流
为了让非技术人员也能使用,我们可以搭建一个简单的前端页面。
7.1 前端功能设计
- 支持拖拽或点击上传图片
- 显示识别进度
- 展示解析后的表格数据(以JSON或表格形式)
- 提供“导出JSON”按钮
项目中已提供基于Vue的前端代码(位于ui/目录),编译打包即可:
cd ui npm install npm run build将生成的dist文件夹复制到SpringBoot项目的src/main/resources/static下。
7.2 访问体验
启动SpringBoot应用后,访问http://localhost:8080,你会看到如下界面:
- 上传一张包含表格的图片(如采购单、发票)
- 点击“识别”按钮
- 几秒后,页面展示识别出的JSON数据或渲染成表格
整个过程无需人工干预,真正实现了“拍照→识别→结构化→入库”的自动化闭环。
8. 打包部署:Docker一体化运行
最后一步,我们将SpringBoot应用与OCR服务一起打包,实现统一运维。
8.1 构建SpringBoot镜像
编写Dockerfile:
FROM openjdk:21-jdk-slim WORKDIR /app COPY target/deepseek-web-ui.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]8.2 编排服务(docker-compose.yml)
version: '3.8' services: ocr-backend: image: deepseek-ocr-webui container_name: deepseek-ocr-webui ports: - "8080:8080" volumes: - ./models:/app/models app: build: . ports: - "8081:8080" depends_on: - ocr-backend environment: - SERVER_PORT=8080启动命令:
docker-compose up -d --build此时:
http://localhost:8080:DeepSeek-OCR-WEBUI 服务http://localhost:8081:我们的SpringBoot应用前端+后端
9. 总结
通过本文的实践,我们完成了从“图片”到“JSON”的完整链路构建:
- 部署OCR服务:利用 DeepSeek-OCR-WEBUI 快速搭建本地识别引擎;
- 精准识别表格:使用
prompt_type=figure模式获取HTML格式的表格; - 结构化解析:在SpringBoot中通过Jsoup将HTML转为JSON;
- 前后端集成:提供Web界面,实现可视化操作;
- 容器化部署:Docker一键启动,便于维护和扩展。
这套方案已在实际项目中验证,可用于:
- 采购单自动入库
- 发票信息提取
- 学生答题卡扫描评分
- 档案数字化归档
相比传统OCR工具,DeepSeek-OCR-WEBUI 在中文表格识别上的表现尤为出色,极大降低了开发门槛和维护成本。
如果你也在处理大量纸质文档,不妨试试这个组合拳:拍个照 → 自动变JSON → 直接进数据库,让数据录入从此告别手工时代。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。