news 2026/5/6 8:12:18

SpringBoot集成DeepSeek-OCR-WEBUI实现表格识别实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot集成DeepSeek-OCR-WEBUI实现表格识别实战

SpringBoot集成DeepSeek-OCR-WEBUI实现表格识别实战

1. 业务背景与技术选型

在企业级应用中,大量纸质单据(如采购订单、发票、入库单等)需要数字化处理。传统人工录入方式效率低、成本高且易出错。通过引入OCR技术,可将图像中的表格内容自动提取为结构化数据,大幅提升数据录入效率。

本项目选择DeepSeek-OCR-WEBUI作为核心识别引擎,原因如下:

  • 支持多语言、复杂版式和低质量图像的高精度识别
  • 提供开箱即用的Web UI与RESTful API接口
  • 对中文场景优化良好,尤其适合国内业务环境
  • 基于Docker部署,易于集成与维护
  • 支持图表解析模式(figure),专为表格、公式等结构化内容设计

SpringBoot作为后端框架,具备快速开发、易于集成第三方服务的优势,非常适合构建此类轻量级OCR接入系统。

2. 环境准备与服务启动

2.1 部署DeepSeek-OCR-WEBUI服务

确保已安装Docker和Docker Compose,并具备至少一张NVIDIA GPU(推荐4090D及以上显卡以获得最佳性能)。

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

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

docker logs -f deepseek-ocr-webui

服务默认监听http://localhost:8080,可通过浏览器访问Web界面进行测试。

2.2 接口说明

DeepSeek-OCR-WEBUI 提供/ocr接口用于图像识别,关键参数如下:

参数名类型可选值说明
fileFile-待识别的图片文件
prompt_typeStringdocument, ocr, free, figure, describe, find, freeform指定识别模式
find_termString-查找并标注特定文本
custom_promptString-自定义提示词
groundingBooleantrue/false是否启用分组

注意:本文目标是识别表格,因此需设置prompt_type=figure,该模式会返回HTML格式的表格结构。


3. SpringBoot集成实现

3.1 项目结构与依赖配置

创建SpringBoot项目,添加以下核心依赖:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.16.1</version> </dependency> </dependencies>
  • fastjson:用于JSON序列化
  • jsoup:解析OCR返回的HTML表格内容

3.2 定义OCR服务接口

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

3.3 实现OCR服务逻辑

// src/main/java/com/example/ocr/service/impl/DeepSeekOcrService.java @Service @Slf4j public class DeepSeekOcrService implements OcrService { private static final String OCR_SERVICE_URL = "http://localhost:8080/ocr"; private static final String PROMPT_TYPE = "figure"; @Value("${deepseek.ocr.timeout:5000}") private int timeout; @Override public Map<String, Object> recognitionTable(MultipartFile file) { log.info("开始识别表格,文件名:{}", file.getOriginalFilename()); RestTemplate restTemplate = new RestTemplate(); restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); try { // 准备文件资源 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", PROMPT_TYPE); // 设置请求头 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() == HttpStatus.OK) { String htmlContent = response.getBody(); log.debug("OCR返回HTML内容:{}", htmlContent); return parseHtmlTableToJSON(htmlContent); } else { log.error("OCR识别失败,HTTP状态码:{}", response.getStatusCode()); throw new RuntimeException("OCR识别失败:" + response.getStatusCode()); } } catch (Exception e) { log.error("调用OCR服务异常", e); throw new RuntimeException("调用OCR服务失败:" + e.getMessage(), e); } } /** * 将HTML表格解析为JSON格式 * * @param html 包含<table>标签的HTML字符串 * @return 转换后的JSON数据,包含表头和行数据 */ private Map<String, Object> parseHtmlTableToJSON(String html) { Document doc = Jsoup.parse(html); Elements tables = doc.select("table"); Map<String, Object> result = new HashMap<>(); if (tables.isEmpty()) { result.put("headers", Collections.emptyList()); result.put("rows", Collections.emptyList()); result.put("success", false); result.put("message", "未检测到表格"); return result; } Element table = tables.first(); List<String> headers = new ArrayList<>(); List<List<String>> rows = new ArrayList<>(); // 解析表头 Elements headerCells = table.select("tr:first-child td"); for (Element cell : headerCells) { headers.add(cell.text().trim()); } // 解析数据行(跳过第一行) Elements dataRows = table.select("tr"); for (int i = 1; i < dataRows.size(); i++) { Element row = dataRows.get(i); Elements cells = row.select("td"); List<String> rowData = new ArrayList<>(); for (Element cell : cells) { rowData.add(cell.text().trim()); } rows.add(rowData); } result.put("success", true); result.put("headers", headers); result.put("rows", rows); result.put("totalRows", rows.size()); return result; } }
核心要点说明:
  1. RestTemplate配置:使用HttpComponentsClientHttpRequestFactory支持大文件上传。
  2. multipart/form-data封装:正确构造带文件和字段的请求体。
  3. HTML解析逻辑
    • 使用Jsoup解析返回的HTML片段
    • 提取首行为表头(headers)
    • 后续行为数据行(rows)
    • 支持空值处理与异常边界判断

3.4 编写单元测试

// src/test/java/com/example/ocr/service/OcrServiceTest.java @SpringBootTest @Slf4j 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, true)); // 断言验证 Assertions.assertTrue((Boolean) result.get("success")); Assertions.assertNotNull(result.get("headers")); Assertions.assertNotNull(result.get("rows")); Assertions.assertEquals(4, ((List<?>) result.get("rows")).size()); } }

测试用例使用MockMultipartFile模拟文件上传,确保服务层逻辑正确性。

3.5 创建控制器接口

// src/main/java/com/example/ocr/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) { try { Map<String, Object> result = ocrService.recognitionTable(file); log.info("表格识别成功,共{}行数据", result.get("totalRows")); return result; } catch (Exception e) { log.error("处理文件时发生错误", e); Map<String, Object> error = new HashMap<>(); error.put("success", false); error.put("message", "识别失败:" + e.getMessage()); return error; } } }

提供/api/ocr/process接口接收前端上传的图片文件,并返回结构化JSON数据。

4. 前后端联调与部署

4.1 前端页面集成

前端采用Vue3搭建简单操作界面,主要功能包括:

  • 文件拖拽上传
  • 图片预览
  • 表格数据展示
  • 结果导出为CSV

编译打包命令:

npm install npm run build

将生成的dist/目录下静态资源复制到SpringBoot项目的src/main/resources/static/目录中。

4.2 后端打包配置

使用Maven打包可执行JAR:

<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>

执行打包:

mvn clean package -DskipTests

生成的JAR位于target/deepseek-web-ui.jar

4.3 Docker容器化部署

Dockerfile
FROM openjdk:21-jdk-slim WORKDIR /app COPY target/deepseek-web-ui.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
docker-compose.yml
version: '3.8' services: ocr-backend: build: . ports: - "8080:8080" environment: - SERVER_PORT=8080 volumes: - ./logs:/app/logs depends_on: - ocr-engine ocr-engine: image: deepseek-ocr-webui:latest container_name: deepseek-ocr-webui ports: - "8081:8080" runtime: nvidia deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu]

注意:OCR引擎与SpringBoot应用分别运行在不同容器中,通过http://ocr-engine:8080内网通信。

启动服务:

docker compose up -d --build

访问http://localhost:8080即可使用完整OCR识别系统。

5. 总结

本文详细介绍了如何将DeepSeek-OCR-WEBUI集成至SpringBoot应用中,实现高效的表格识别功能。核心成果包括:

  1. ✅ 成功对接DeepSeek OCR API,利用其figure模式精准识别复杂表格
  2. ✅ 实现HTML表格到JSON的结构化解析,便于前端展示与后续处理
  3. ✅ 构建完整的前后端一体化解决方案,支持本地或容器化部署
  4. ✅ 提供可复用的服务封装与错误处理机制,具备生产可用性

该方案已在实际项目中验证,能有效替代人工录入,提升单据处理效率80%以上。未来可扩展方向包括:

  • 添加异步处理队列支持大批量任务
  • 集成校验规则引擎自动修正异常数据
  • 支持PDF多页文档批量识别

获取更多AI镜像

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

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

微调结果可验证!Qwen2.5-7B前后对比演示

微调结果可验证&#xff01;Qwen2.5-7B前后对比演示 1. 引言&#xff1a;低资源高效微调的实践价值 在大模型时代&#xff0c;如何以最低成本实现模型能力定制化&#xff0c;是开发者关注的核心问题。通义千问团队发布的 Qwen2.5-7B-Instruct 模型凭借其出色的推理能力和中文…

作者头像 李华
网站建设 2026/5/2 18:15:10

verl快速入门手册:一句话启动训练任务

verl快速入门手册&#xff1a;一句话启动训练任务 1. 引言 1.1 大型语言模型后训练的挑战 随着大型语言模型&#xff08;LLMs&#xff09;在自然语言处理领域的广泛应用&#xff0c;如何高效地进行模型对齐与行为优化成为关键问题。传统的监督微调&#xff08;SFT&#xff0…

作者头像 李华
网站建设 2026/4/27 23:31:48

Qwen3-Embedding-4B部署指南:多模型协同工作方案

Qwen3-Embedding-4B部署指南&#xff1a;多模型协同工作方案 1. 引言 随着大模型在语义理解、信息检索和知识管理等场景的广泛应用&#xff0c;高质量的文本向量化能力成为构建智能系统的核心基础。通义千问团队于2025年8月开源了Qwen3-Embedding-4B——一款专为高效、高精度…

作者头像 李华
网站建设 2026/4/27 15:45:53

炉石传说插件终极优化指南:5大效率革命与高阶玩法深度揭秘

炉石传说插件终极优化指南&#xff1a;5大效率革命与高阶玩法深度揭秘 【免费下载链接】HsMod Hearthstone Modify Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 在快节奏的炉石传说对战中&#xff0c;每一秒都至关重要。HsMod插件基于Bep…

作者头像 李华
网站建设 2026/5/1 17:57:13

终极炉石传说插件指南:10个必知技巧让你的游戏效率翻倍!

终极炉石传说插件指南&#xff1a;10个必知技巧让你的游戏效率翻倍&#xff01; 【免费下载链接】HsMod Hearthstone Modify Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 想要在《炉石传说》中实现游戏效率的质的飞跃吗&#xff1f;&…

作者头像 李华
网站建设 2026/5/1 10:47:34

树莓派课程设计小项目实战案例:LED控制入门

从点亮第一盏灯开始&#xff1a;树莓派LED控制实战教学手记还记得你第一次亲手让硬件“动起来”的那一刻吗&#xff1f;对很多电子工程初学者来说&#xff0c;那往往就是——按下电源&#xff0c;LED亮了。在如今这个物联网与智能设备无处不在的时代&#xff0c;树莓派&#xf…

作者头像 李华