|
|
@@ -117,6 +117,21 @@ public class PdfParseService {
|
|
|
private static final List<String> KNOWN_PATHOGENS = Arrays.asList(
|
|
|
"幽门螺杆菌", "艰难梭菌", "沙门氏菌", "志贺氏菌", "弯曲杆菌");
|
|
|
|
|
|
+ // ======================== 分页残段清洗(T12/L1-2 分页残段清洗下沉) ========================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页残段标记样例(计划 §2.1 / T12)。
|
|
|
+ * 「与健康相关菌评估」分页表拼接残段样例 {@code 34/167 0.0033 参考 0-0.1746% ND},
|
|
|
+ * 其中 {@code 34/167} 为分页页码拼接残段;个人层丰度不再混入知识层。
|
|
|
+ */
|
|
|
+ private static final String PAGE_TAIL_SAMPLE = "34/167";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页残段断言正则(T12/L1-2 校验层断言:物种库条目不含 {@code \d{1,3}/16\d})。
|
|
|
+ * 匹配分页页码拼接残段(如 {@code 34/167});Java 字符串中 {@code \d} 转义为 {@code \\d}。
|
|
|
+ */
|
|
|
+ private static final String PAGE_TAIL_ASSERT_REGEX = "\\d{1,3}/16\\d";
|
|
|
+
|
|
|
// ======================== 主入口 ========================
|
|
|
|
|
|
/**
|
|
|
@@ -148,6 +163,10 @@ public ParsedReportResult parseText(String fullText) {
|
|
|
return beijingResult;
|
|
|
}
|
|
|
|
|
|
+ // T12/L1-2 分页残段清洗下沉:guhe 报告解析前自动剥离分页表拼接残段,
|
|
|
+ // Adapter 调用 parseText() 即自动获得清洗(无需单独调用),个人层丰度不再混入知识层。
|
|
|
+ normalized = stripTableTail(normalized);
|
|
|
+
|
|
|
// 3. 按行分割
|
|
|
String[] lines = normalized.split("\r?\n");
|
|
|
List<String> lineList = new ArrayList<>();
|
|
|
@@ -181,6 +200,56 @@ public ParsedReportResult parseText(String fullText) {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ // ======================== 分页残段清洗入口(T12/L1-2,_strip_table_tail 的 Java 下沉) ========================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页残段清洗执行入口(Python {@code _strip_table_tail()} 的 Java 下沉)。
|
|
|
+ *
|
|
|
+ * <p>根治「与健康相关菌评估」分页表拼接残段(如 {@code 34/167 0.0033 参考 0-0.1746% ND}):
|
|
|
+ * 剥离含分页页码拼接模式({@code \d{1,3}/16\d},如 {@code 34/167})的残段行,
|
|
|
+ * 使个人层丰度不再混入知识层。guhe 报告解析({@link #parseText})时自动调用,
|
|
|
+ * Adapter 无需单独触发即自动获得清洗。</p>
|
|
|
+ *
|
|
|
+ * @param text guhe 报告全文(已归一化 Kangxi 部首)
|
|
|
+ * @return 剥离分页残段行后的文本
|
|
|
+ */
|
|
|
+ public String stripTableTail(String text) {
|
|
|
+ if (text == null || text.isEmpty()) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ Pattern tailPattern = Pattern.compile(PAGE_TAIL_ASSERT_REGEX);
|
|
|
+ String[] lines = text.split("\r?\n", -1);
|
|
|
+ StringBuilder sb = new StringBuilder(text.length());
|
|
|
+ int removed = 0;
|
|
|
+ for (String line : lines) {
|
|
|
+ if (tailPattern.matcher(line).find()) {
|
|
|
+ removed++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ sb.append(line).append('\n');
|
|
|
+ }
|
|
|
+ if (removed > 0) {
|
|
|
+ log.debug("分页残段清洗: 剥离 {} 行分页表拼接残段(模式 {})", removed, PAGE_TAIL_ASSERT_REGEX);
|
|
|
+ }
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页残段清洗校验断言入口(T12/L1-2 校验层:物种库条目不含 {@code \d{1,3}/16\d})。
|
|
|
+ *
|
|
|
+ * <p>断言清洗后产物「残段 0 命中」——文本中不存在分页页码拼接残段模式。
|
|
|
+ * 供解析管线在校验层调用,程序化校验清洗效果。</p>
|
|
|
+ *
|
|
|
+ * @param cleanedText 清洗后文本(或任一物种库条目字符串)
|
|
|
+ * @return true 表示残段 0 命中(校验通过);false 表示仍存在分页残段
|
|
|
+ */
|
|
|
+ public boolean assertTailClean(String cleanedText) {
|
|
|
+ if (cleanedText == null || cleanedText.isEmpty()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return !Pattern.compile(PAGE_TAIL_ASSERT_REGEX).matcher(cleanedText).find();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 归一化 Kangxi 部首到标准 CJK 汉字
|
|
|
*/
|