news 2026/9/2 23:03:34

SpringBoot接入DeepSeek-OCR实现结构化数据提取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot接入DeepSeek-OCR实现结构化数据提取

SpringBoot接入DeepSeek-OCR实现结构化数据提取

在企业级应用中,纸质单据、发票、合同等文档的数字化处理一直是一个高频且繁琐的任务。传统的人工录入方式不仅效率低下,还容易出错。随着AI技术的发展,尤其是OCR(光学字符识别)能力的显著提升,自动化提取图像中的文本信息已成为可能。

本文将带你一步步实现SpringBoot应用接入DeepSeek-OCR-WEBUI服务,重点解决一个典型业务场景:从包含表格的图片中自动识别并提取结构化数据,最终转换为JSON格式供系统使用。整个过程涵盖后端部署、接口调用、HTML解析、前后端集成与Docker打包发布,是一套可直接落地的企业级解决方案。


1. 部署DeepSeek-OCR-WEBUI服务

要让SpringBoot应用能够调用OCR功能,首先需要确保DeepSeek-OCR-WEBUI服务已经正确部署并运行。该镜像基于DeepSeek开源的大模型,具备强大的文本检测与识别能力,尤其擅长处理复杂布局的文档内容,如表格、公式、多语言混合文本等。

1.1 启动OCR服务

进入项目目录并使用Docker Compose启动服务:

cd ~/DeepSeek-OCR-WebUI docker compose up -d

启动完成后,查看日志确认服务是否正常运行:

docker logs -f deepseek-ocr-webui

当看到类似Uvicorn running on http://0.0.0.0:8080的输出时,说明Web API服务已就绪。

1.2 OCR核心接口说明

服务暴露了一个关键POST接口用于图像识别:

POST /ocr

支持以下参数:

参数名类型可选值说明
fileFile-要上传的图像文件
prompt_typestringdocument,ocr,free,figure,describe,find,freeform指定识别模式
find_termstring自定义关键词仅在find模式下有效
custom_promptstring-自定义提示词
groundingbooleantrue / false是否启用分组

本案例重点使用prompt_type=figure,因为该模式专为图表和表格设计,能更准确地保留原始结构,输出HTML格式的表格代码。

例如,传入一张采购单截图,设置prompt_type=figure,返回结果将是标准的<table>HTML片段,便于后续结构化解析。


2. SpringBoot项目结构设计

我们的目标是构建一个轻量但完整的Web应用,接收用户上传的含表格图片,调用OCR服务完成识别,并将结果以JSON形式返回给前端展示或入库。

2.1 技术栈选择

  • 后端框架:Spring Boot 3.x
  • HTTP客户端:RestTemplate(简化远程调用)
  • JSON处理:Fastjson
  • 前端:Vue3 + Element Plus(静态页面嵌入)
  • 打包部署:Docker + docker-compose

2.2 核心模块划分

模块功能描述
OcrService定义OCR识别接口
DeepSeekOcrService实现类,封装对OCR服务的HTTP调用
OcrController提供REST API供前端调用
HtmlParser将OCR返回的HTML表格转为List结构
Vue UI用户操作界面,支持图片上传与结果显示

3. 实现OCR服务调用逻辑

3.1 定义服务接口

// src/main/java/com/kaifamiao/dswebui/service/OcrService.java public interface OcrService { /** * 识别表格图片并返回结构化数据 * * @param file 上传的包含表格的图片文件 * @return 包含表格数据的Map对象,将以JSON格式返回给前端 */ Map<String, Object> recognitionTable(MultipartFile file); }

3.2 实现远程调用与HTML解析

// src/main/java/com/kaifamiao/dswebui/service/DeepSeekOcrService.java @Service @Slf4j public class DeepSeekOcrService implements OcrService { private static final String OCR_SERVICE_URL = "http://localhost:8080/ocr"; @Override public Map<String, Object> recognitionTable(MultipartFile file) { log.info("开始处理文件: {}", file.getOriginalFilename()); try { RestTemplate restTemplate = new RestTemplate(); // 准备文件资源 ByteArrayResource resource = new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { return file.getOriginalFilename(); } }; // 构建请求参数 MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("file", resource); body.add("prompt_type", "figure"); // 关键:使用图表模式识别表格 // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); // 创建请求实体 HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); // 发送POST请求 ResponseEntity<String> response = restTemplate.postForEntity(OCR_SERVICE_URL, requestEntity, String.class); if (response.getStatusCode().is2xxSuccessful()) { String htmlContent = response.getBody(); log.info("OCR返回HTML长度: {}", htmlContent.length()); return parseHtmlTableToJSON(htmlContent); } else { log.error("OCR服务调用失败,状态码: {}", response.getStatusCode()); throw new RuntimeException("OCR识别失败"); } } catch (Exception e) { log.error("OCR识别过程中发生异常", 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"); if (table == null) return Collections.emptyMap(); List<Element> rows = table.select("tr"); if (rows.isEmpty()) return Collections.emptyMap(); // 提取表头 List<String> headers = new ArrayList<>(); Elements headerCells = rows.get(0).select("td, th"); for (Element cell : headerCells) { headers.add(cell.text().trim()); } // 提取数据行 List<Map<String, String>> dataRows = new ArrayList<>(); for (int i = 1; i < rows.size(); i++) { Elements cells = rows.get(i).select("td"); Map<String, String> row = new HashMap<>(); for (int j = 0; j < Math.min(cells.size(), headers.size()); j++) { String key = headers.get(j); String value = cells.get(j).text().trim(); row.put(key, value.isEmpty() ? "" : value); } dataRows.add(row); } // 组装返回结果 Map<String, Object> result = new HashMap<>(); result.put("headers", headers); result.put("data", dataRows); result.put("totalRows", dataRows.size()); return result; } }
依赖说明

需引入以下Maven依赖:

<!-- JSoup用于HTML解析 --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.16.1</version> </dependency> <!-- Fastjson用于JSON序列化 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency>

4. 编写控制器暴露API

// src/main/java/com/kaifamiao/dswebui/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) { if (file.isEmpty()) { throw new IllegalArgumentException("上传文件不能为空"); } long startTime = System.currentTimeMillis(); Map<String, Object> result = ocrService.recognitionTable(file); long costTime = System.currentTimeMillis() - startTime; result.put("success", true); result.put("costTimeMs", costTime); log.info("OCR识别完成,耗时{}ms", costTime); return result; } }

该接口接收名为file的图片上传请求,调用服务层处理后返回结构化数据,包含字段名、每行数据及统计信息。


5. 添加测试用例验证功能

为了确保服务稳定性,编写单元测试验证全流程可用性。

// src/test/java/com/kaifamiao/dswebui/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识别结果: \n{}", JSON.toJSONString(result, true)); Assertions.assertNotNull(result.get("data")); Assertions.assertTrue(((List<?>) result.get("data")).size() > 0); } }

运行测试,观察日志输出是否成功解析出表格内容。


6. 前端页面集成(Vue3)

前端采用Vue3 + Element Plus搭建简易交互界面,主要功能包括:

  • 图片上传区域
  • 实时预览
  • 表格数据显示
  • 错误提示

6.1 页面结构示例

<template> <div class="container"> <h2>表格图片OCR识别</h2> <el-upload action="/api/ocr/process" :auto-upload="true" :show-file-list="false" accept="image/*" :on-success="handleSuccess" :on-error="handleError"> <img v-if="imageUrl" :src="imageUrl" class="preview-img"/> <el-button>点击上传表格图片</el-button> </el-upload> <div v-if="tableData.length > 0" class="result-table"> <h3>识别结果</h3> <el-table :data="tableData" border style="width: 100%"> <el-table-column v-for="col in columns" :key="col" :prop="col" :label="col" /> </el-table> </div> </div> </template>

6.2 构建与集成

进入前端目录执行构建:

npm install npm run build

将生成的dist文件夹内容复制到SpringBoot项目的src/main/resources/static目录下,即可通过内置Tomcat直接访问UI。


7. Docker打包与一键部署

完成开发后,我们将整个应用容器化,便于部署到生产环境。

7.1 编写Dockerfile

FROM openjdk:21-jdk-slim WORKDIR /app COPY target/deepseek-web-ui.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

7.2 编排服务(docker-compose.yml)

version: '3.8' services: ocr-app: build: . ports: - "8080:8080" environment: - SERVER_PORT=8080 volumes: - ./logs:/app/logs

7.3 构建并启动

mvn clean package -DskipTests docker compose up -d --build

访问http://localhost:8080即可打开OCR识别页面,上传图片即可实时获取结构化数据。


8. 总结

本文完整演示了如何将DeepSeek-OCR-WEBUI这一高性能OCR引擎集成进SpringBoot应用,实现了从“图片→HTML表格→JSON结构化数据”的全链路自动化提取流程。这套方案具有以下优势:

  • 高精度识别:利用DeepSeek大模型的强大能力,准确还原复杂表格结构;
  • 低耦合设计:通过HTTP接口调用,OCR服务可独立升级维护;
  • 易扩展性强:支持多种prompt_type,未来可拓展至合同解析、发票识别等场景;
  • 快速落地:提供完整前后端代码与Docker部署脚本,开箱即用。

无论是财务报销、物流运单、库存管理还是教育阅卷,只要涉及纸质表格电子化,都可以基于此方案进行定制开发,大幅提升数据录入效率,降低人工成本。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/26 1:07:42

Qwen-Image-2512功能测评:中文渲染与图像编辑表现如何

Qwen-Image-2512功能测评&#xff1a;中文渲染与图像编辑表现如何 1. 引言&#xff1a;为什么这款模型值得关注&#xff1f; 你有没有遇到过这样的尴尬&#xff1f;输入一段精心设计的中文提示词&#xff0c;结果生成的图片里文字全是乱码、错位&#xff0c;甚至干脆不显示。…

作者头像 李华
网站建设 2026/9/2 17:06:13

3步零基础打造p5.js音乐可视化:让代码与旋律共舞 ✨

3步零基础打造p5.js音乐可视化&#xff1a;让代码与旋律共舞 ✨ 【免费下载链接】p5.js p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the co…

作者头像 李华
网站建设 2026/8/31 15:25:03

palera1n越狱终极指南:从新手到专家的完整操作手册

palera1n越狱终极指南&#xff1a;从新手到专家的完整操作手册 【免费下载链接】palera1n Jailbreak for arm64 devices on iOS 15.0 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n 还在为iOS系统的限制而苦恼吗&#xff1f;想要完全掌控你的iPhone设备&a…

作者头像 李华
网站建设 2026/9/2 16:00:12

餐厅环境评估:顾客满意度语音AI检测部署案例

餐厅环境评估&#xff1a;顾客满意度语音AI检测部署案例 1. 引言&#xff1a;用声音感知顾客情绪&#xff0c;重新定义餐厅体验管理 你有没有过这样的经历&#xff1f;走进一家餐厅&#xff0c;明明装修不错、菜品也还行&#xff0c;但就是感觉“哪里不对”——氛围冷清、服务…

作者头像 李华
网站建设 2026/8/25 16:12:34

iPad越狱完全指南:从入门到精通的技术实践

iPad越狱完全指南&#xff1a;从入门到精通的技术实践 【免费下载链接】palera1n Jailbreak for arm64 devices on iOS 15.0 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n 随着iOS系统的不断更新&#xff0c;越来越多的用户希望能够突破系统限制&#xf…

作者头像 李华