migration-python-to-java-report-parsing.md 9.0 KB

Python → Java 报告解析迁移计划

背景

菌群报告和 DAN 测评报告的 Python 解析脚本(docs/参考资料/)是离线数据预处理工具。Java 运行时(cfc-backend/)已有部分实现但覆盖不全。

现状

解析器 Java 现状 Python 覆盖 差距
菌群报告 PdfParseService ✅ 868行,PDFBox,完整 extract_full_report_v5.py 1393行 持平,Java 已可用于生产
DAN A2 (mind) ✅ 已完成 extract_a2_data() 持平
DAN B4 (wisdom) ✅ 已完成 extract_b4_data() 持平
DAN A1 儿童认知 ❌ 未实现 extract_a1_data() 需移植
DAN B2 儿童行为 ❌ 未实现 extract_b2_data() 需移植
DAN B3 学习能力 ❌ 未实现 extract_b3_data() 需移植
DAN B5 青春期 ❌ 未实现 extract_b5_data()(含仪表盘图片分析) 需移植
DAN B6 职业发展 ❌ 未实现 extract_b6_data() 需移植
DAN C1 校园版 ❌ 未实现 extract_c1_data() 需移植

总体策略

菌群报告:Java 已满足生产需求,不做变动。Python 脚本保留为离线参考。

DAN 报告:分3波迁移。每波包含:解析逻辑 → 新增 Controller 端点 → 测试验证。


Wave 1 — 基础类型(A1 + B3)

目标:纯文本正则提取,无图片分析,约 140 行 Python → Java

A1 儿童核心认知发展

Python: extract_a1_data() ~43 行

  • 6 个认知维度:感知觉、注意力、记忆力、推理能力、空间能力、加工速度
  • 提取逻辑:正则匹配 3 种 PDF 格式(summary 页百分位、detail 页得分+百分位、fallback)
  • 输出格式:{维度名_pct, 维度名_score}

Java 实现方案

  • DanReportParseService 中新增 parseA1Report(List<String> lines, String fullText) 方法
  • 复用现有的 DataItemDanParsedReport 结构
  • 维度映射到 dan_assessment_results 表的 attention_score, memory_score, perception_score, spatial_score, processing_speed_score, logic_score 字段
  • 新增 dimension="cognition" 路由分支(parseText() 中)

B3 核心学习能力

Python: extract_b3_data() ~74 行

  • 3 大模块:执行功能(认知灵活性/抑制控制/元认知)、学习动机(内在/外在)、学习策略(深层/表面)
  • 提取逻辑:章节分割 + 正则匹配分数

Java 实现方案

  • 新增 parseB3Report() 方法
  • 复用 findSectionStart() + parseScorePairs() 模式
  • 新增 dimension="learning" 路由分支

Wave 1 改动范围

DanReportParseService.java
├── parseText(): 新增 "cognition" / "learning" 路由
├── parseA1Report()        ← 新增,~60 行
├── parseB3Report()        ← 新增,~80 行
├── parseScorePairs()      ← 新增辅助方法,复用正则
└── DataItem / DanParsedReport 结构不变

DanAssessmentController.java
├── parsePreview(): 放开 dimension 校验(当前只允许 mind/wisdom)
└── dimension 映射表: cognition→A1, learning→B3

schema.sql / DatabaseInitializer
└── 无需新增表(dan_assessment_results 已有 JSON 字段 structured_analysis)

Wave 2 — 中等复杂度(B2 + B6 + C1)

B2 儿童自我与家庭教养

Python: extract_b2_data() ~74 行

  • 自我概念 6 维 + 儿童行为 8 维 + 家庭环境 10 维
  • 提取逻辑:章节定位 + 正则匹配

Java 实现方案

  • 新增 parseB2Report() 方法
  • 复用 parseSelfConcept()(已存在于 B4 解析中)
  • 新增行为、家庭环境的提取方法
  • 新增 dimension="behavior" 路由

B6 职业发展

Python: extract_b6_data() ~77 行

  • Holland 兴趣 6 型(RIASEC)+ 多元智能 8 维 + 职业价值观
  • 提取逻辑:表格文本正则匹配

Java 实现方案

  • 新增 parseB6Report() 方法
  • 新增 dimension="career" 路由

C1 校园版

Python: extract_c1_data() ~91 行

  • 认知 6 维(同 A1)+ 大五人格 5 维(同 A2)+ 自驱力 3 维 + 自我概念 6 维
  • 提取逻辑:复用 A1 和 A2 的维度提取

Java 实现方案

  • 新增 parseC1Report() 方法
  • 复用 parseA1Report() 的认知维度提取 + A2 的大五人格提取
  • 新增 dimension="campus" 路由

Wave 2 改动范围

DanReportParseService.java
├── parseText(): 新增 "behavior"/"career"/"campus" 路由
├── parseB2Report()         ← 新增,~80 行
├── parseB6Report()         ← 新增,~80 行
├── parseC1Report()         ← 新增,~60 行(复用现有方法)
├── parseFamilyEnvironment() ← 新增辅助方法
├── parseHollandInterest()   ← 新增辅助方法
└── parseMultipleIntelligence() ← 新增辅助方法

DanAssessmentController.java
└── 路由映射扩展

schema.sql / DatabaseInitializer
└── 无需新增表

Wave 3 — 高复杂度(B5 青春期 + B4 增强)

B5 青春期挑战

Python: extract_b5_data() + 罗盘仪表盘图片分析 ~150 行

  • 情绪调节 2 维 + 学业压力 5 维 + 人际关系 4 维 + 社交 5 维 + 睡眠/运动/网络
  • 特殊:B5 报告含 指南针仪表盘图像,Python 用 PyMuPDF 提取 PNG + 像素分析

Java 实现方案

  • 文本部分:新增 parseB5Report(),正则提取各维度分数,这覆盖 80% 的数据
  • 图像部分(指南针仪表盘):
    1. 用 PDFBox 提取页面图像 PDImageXObject
    2. 用 Java BufferedImage 做像素颜色分析(替代 Python 的 PIL 角度测量)
    3. 或:降级方案——跳过图像分析,仅从文本提取可读分数(文本已包含主要维度的数字评分)
  • 新增 dimension="adolescent" 路由

谨慎意见:B5 指南针仪表盘是 PNG 嵌入图像,PDFBox 可以提取,但像素级别的指针角度分析在 Java 中更啰嗦(需用 BufferedImage.getRGB() 手动实现)。可以考虑:

  • 方案 A:纯 Java 实现完整图像分析(2-3 天工作量)
  • 方案 B:跳过图像分析,从文本提取所有维度分数(文本里已有 80% 的数据),1 天内完成
  • 建议:先做方案 B,文本提取覆盖核心数据,图像部分延后

Wave 3 改动范围

DanReportParseService.java
├── parseText(): 新增 "adolescent" 路由
├── parseB5Report()         ← 新增,~120 行(文本部分)
├── parseB5CompassImage()   ← 可选,降级优先
└── extractImageFromPDF()   ← 新增辅助(PDFBox→BufferedImage)

DanAssessmentController.java
└── 路由映射扩展 + 处理 B5 图片分析结果

schema.sql / DatabaseInitializer
└── 无需新增表

测试策略

每波完成后验证:

cfc-backend/src/test/java/.../DanReportParseServiceTest.java
├── testParseA1Report()     — 用真实 A1 PDF 测试 6 维度提取
├── testParseB3Report()     — 用真实 B3 PDF 测试
├── testParseA2Report()     — 已有,确认回归
├── testParseB4Report()     — 已有,确认回归
├── testParseB2Report()     — Wave 2
├── testParseB6Report()     — Wave 2
├── testParseC1Report()     — Wave 2
└── testParseB5Report()     — Wave 3

HealthReportControllerTest.java
└── testUploadGutFloraReport() — 回归确认菌群报告不受影响

测试用 PDFdocs/参考资料/dan_reports/ 下已有各类型真实 PDF 样本。

验证命令

cd cfc-backend && mvn clean compile test -Dtest=DanReportParseServiceTest

不会改动的内容

  • 菌群报告的 Python extract_full_report_v5.py:保留为离线参考
  • DAN Python 脚本集合 dan_reports/:完整保留,不删除
  • PdfParseService.java:不做任何改动
  • HealthReportController.java:不做任何改动
  • DB schema:不需要新增表dan_assessment_results.structured_analysis(JSON 字段)已支持所有 DAN 报告类型的结构化数据存储

总工作量估算

Wave 新增 Java 行数 类型数 复杂度 估计工时
Wave 1 (A1+B3) ~140 2 1-2 天
Wave 2 (B2+B6+C1) ~220 3 2-3 天
Wave 3 (B5) ~150 1 1-2 天(文本)/ +2天(图像)
合计 ~510 6 4-7 天

变更风险矩阵

Risk 影响 缓解措施
Python 正则与 PDF 实际格式强耦合,不同 PDF 版本格式不同 提取失败/漏数据 测试覆盖多种 PDF 样本;Java 中用多模式回退(Python 已有多模式模式,直接移植)
PDFBox 文本提取顺序和 PyMuPDF 不同 正则不匹配 parseText() 中增加行合并预处理;对比 5+ 份 PDF 输出
B5 图片分析在 PDFBox 中比 PyMuPDF 更复杂 开发成本翻倍 Wave 3 先做文本部分,图片分析延后独立
DanAssessmentController 现有接口调用方依赖 mind/wisdom 前端不兼容 向后兼容:老 dimension 值保持可用,新值只影响解析路径