news 2026/2/28 4:45:53

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/2/26 0:43:53

NewBie-image-Exp0.1实战:用XML结构化提示词打造专属角色

NewBie-image-Exp0.1实战&#xff1a;用XML结构化提示词打造专属角色 1. 引言 1.1 项目背景与核心价值 在当前生成式AI快速发展的背景下&#xff0c;高质量动漫图像生成已成为内容创作、角色设计和虚拟IP开发的重要工具。然而&#xff0c;传统文本提示&#xff08;Prompt&am…

作者头像 李华
网站建设 2026/2/27 20:18:45

MinerU模型体积多大?磁盘空间预估与清理建议

MinerU模型体积多大&#xff1f;磁盘空间预估与清理建议 1. 引言 1.1 场景背景 在当前文档数字化和知识自动化处理的浪潮中&#xff0c;从复杂排版的 PDF 文件中精准提取结构化内容成为一项关键需求。尤其在科研、教育、出版等领域&#xff0c;PDF 文档常包含多栏布局、数学…

作者头像 李华
网站建设 2026/2/27 4:59:39

lora-scripts本地部署:个人电脑从安装到出图完整流程

lora-scripts本地部署&#xff1a;个人电脑从安装到出图完整流程 1. 引言 随着个性化生成需求的不断增长&#xff0c;LoRA&#xff08;Low-Rank Adaptation&#xff09;微调技术因其轻量化、高效训练和即插即用的优势&#xff0c;成为大模型定制化的重要手段。然而&#xff0…

作者头像 李华
网站建设 2026/2/27 8:43:25

LangFlow工具集成:连接天气、搜索、数据库等实用插件

LangFlow工具集成&#xff1a;连接天气、搜索、数据库等实用插件 1. 简介与核心价值 LangFlow 是一款低代码、可视化的 AI 应用构建工具&#xff0c;专为快速搭建和实验 LangChain 流水线而设计。它通过图形化界面将复杂的链式逻辑抽象为可拖拽的节点组件&#xff0c;极大降低…

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

B站视频下载去水印终极指南:3步轻松获取纯净视频

B站视频下载去水印终极指南&#xff1a;3步轻松获取纯净视频 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#xff09…

作者头像 李华
网站建设 2026/2/27 1:23:34

ESP32与OneNet通信:数据点上传稳定性分析

ESP32对接OneNet&#xff1a;如何让数据上传“永不掉线”&#xff1f;你有没有遇到过这样的场景&#xff1f;一个部署在农田温室里的ESP32节点&#xff0c;连续三天风平浪静地上传温湿度数据&#xff0c;结果一场雷雨过后Wi-Fi断了十分钟&#xff0c;等网络恢复时却发现平台上的…

作者头像 李华