Jelajahi Sumber

fix: bacteria table inline parsing, pathogen tables, antibiotic dedup, harmful/other bacteria expansion

asus 2 bulan lalu
induk
melakukan
4b9dcabdca

+ 298 - 49
docs/参考资料/501999942-某人.json

@@ -307,51 +307,6 @@
     }
   ],
   "抗生素风险评估": [
-    {
-      "名称": "β-内酰胺酶类",
-      "数值": "20",
-      "状态": "正常"
-    },
-    {
-      "名称": "氨基糖苷类",
-      "数值": "5",
-      "状态": "正常"
-    },
-    {
-      "名称": "大环内酯类",
-      "数值": "39",
-      "状态": "正常"
-    },
-    {
-      "名称": "呋喃类",
-      "数值": "82",
-      "状态": "正常"
-    },
-    {
-      "名称": "喹诺酮类",
-      "数值": "30",
-      "状态": "正常"
-    },
-    {
-      "名称": "磺胺类",
-      "数值": "61",
-      "状态": "正常"
-    },
-    {
-      "名称": "甲氧苄啶类",
-      "数值": "55",
-      "状态": "正常"
-    },
-    {
-      "名称": "氯霉素类",
-      "数值": "8",
-      "状态": "正常"
-    },
-    {
-      "名称": "四环素类",
-      "数值": "48",
-      "状态": "正常"
-    },
     {
       "名称": "β-内酰胺酶类",
       "数值": "20",
@@ -3322,6 +3277,56 @@
         "人群水平%": "97.60%",
         "说明": "说明:消化复合碳水化合物,健康菌,偏低与炎症肠病,营养不良相关,减肥有效菌,缓解炎症性疾病和代谢疾病,"
       },
+      {
+        "名称": "戴阿利斯特杆菌属 Dialister",
+        "丰度%": "0.0769",
+        "正常范围%": "0-13.9606",
+        "人群水平%": "46%",
+        "检出率%": "96.15%",
+        "说明": "说明:代谢碳水化合物、产短链脂肪酸,许多种都可能导致感染,但是抑郁症患者缺乏,关节炎患者富集,"
+      },
+      {
+        "名称": "罗氏菌属 Roseburia",
+        "丰度%": "1.1301"
+      },
+      {
+        "名称": "2.0832-31.457",
+        "丰度%": "57%",
+        "人群水平%": "96.15%",
+        "说明": "说明:基石菌,产丁酸,丙酸,⼄酸,影响结肠运动,具抗炎特性,分解不可消化的碳水化合物,百岁老⼈富集,抗炎,"
+      },
+      {
+        "名称": "直肠真杆菌属 Agathobacter",
+        "丰度%": "0.1342",
+        "正常范围%": "0-10.7816",
+        "人群水平%": "40%",
+        "检出率%": "95.67%",
+        "说明": "说明:可利用抗性淀粉,具有抗炎和调节免疫功能的作用,类⻛湿性关节炎和溃疡性结肠炎⼈群显著减少。"
+      },
+      {
+        "名称": "吉米菌属 Gemmiger",
+        "丰度%": "0.1955",
+        "正常范围%": "0-5.149",
+        "人群水平%": "40%",
+        "检出率%": "95.67%",
+        "说明": "说明:健康饮食,⾼果蔬、谷物及豆类饮食含量⾼,与雄激素分泌相关,缓解便秘,与脂肪堆积分布负相关,"
+      },
+      {
+        "名称": "副拟杆菌属 Parabacteroides",
+        "丰度%": "0.7216",
+        "正常范围%": "0-5.433",
+        "人群水平%": "45%",
+        "检出率%": "95.19%",
+        "说明": "说明:帮助糖脂代谢,改善⾼脂影响,产生强大的降解酶,参与胆碱代谢,顺产宝宝和⻓寿老⼈肠道丰富,"
+      },
+      {
+        "名称": "另枝菌属 Alistipes",
+        "丰度%": "1.0104",
+        "正常范围%": "0-20.1524",
+        "人群水平%": "71%",
+        "检出率%": "91.83%",
+        "说明": "说明:耐胆汁酸菌,丙酸,⼄酸生产者,参与腐败途径产生氨、H2S、甲酚、吲哚和苯酚,诱发结直肠癌,"
+      },
       {
         "名称": "母螺菌属 Lachnospira",
         "丰度%": "0.1943",
@@ -3460,7 +3465,56 @@
         "正常范围%": "0-0.0066",
         "人群水平%": "96%",
         "检出率%": "7.69%",
-        "说明": "说明:好氧菌,腹泻致病菌,与河流海洋污染相关的潜在"
+        "说明": "说明:好氧菌,腹泻致病菌,与河流海洋污染相关的潜在病原菌,⼈畜共患菌"
+      },
+      {
+        "名称": "厌氧螺菌 Anaerobiospirillum",
+        "丰度%": "ND"
+      },
+      {
+        "名称": "99%",
+        "丰度%": "0.00%",
+        "说明": "说明:引起腹泻,感染,常⻅于猫狗体内,过多会导致菌群紊乱"
+      },
+      {
+        "名称": "肠球菌属 Enterococcus",
+        "丰度%": "ND",
+        "正常范围%": "0-1.1362",
+        "人群水平%": "41%",
+        "检出率%": "81.25%",
+        "说明": "说明:常⻅上呼吸道,⼝腔或肠道的常居菌,也分布在畜、禽养殖环境,饲料或肠道,抑菌调节肠道菌群,"
+      },
+      {
+        "名称": "奈瑟氏菌属 Neisseria",
+        "丰度%": "ND",
+        "正常范围%": "0-0.05",
+        "人群水平%": "80%",
+        "检出率%": "46.15%",
+        "说明": "说明:部分为⼈体病原菌,⼝腔,唾液,⿐腔,肺部正常菌,需氧,对干燥、热、消毒剂敏感,"
+      },
+      {
+        "名称": "不动杆菌属 Acinetobacter",
+        "丰度%": "ND",
+        "正常范围%": "0-0.2475",
+        "人群水平%": "57%",
+        "检出率%": "45.19%",
+        "说明": "说明:条件致病菌,医院感染病原体之⼀,尤其ICU,易引起呼吸道感染、泌尿道感染、创伤感染,"
+      },
+      {
+        "名称": "假单胞菌属 Pseudomonas",
+        "丰度%": "ND",
+        "正常范围%": "0-0.0864",
+        "人群水平%": "54%",
+        "检出率%": "45.19%",
+        "说明": "说明:属于变形菌⻔,在环境中⼴泛存在,代谢多变适应⼒强,好氧或微需,会导致感染和食物变质,医院获得性感染主要原因,"
+      },
+      {
+        "名称": "霍尔德曼氏菌属 Holdemania",
+        "丰度%": "0.0100",
+        "正常范围%": "0-0.0378",
+        "人群水平%": "74%",
+        "检出率%": "29.33%",
+        "说明": "说明:肠道共生菌,降解黏蛋白,机会致病菌,少数研究表明与痛⻛正相关,帕金森,双向情感障碍,过敏,抑郁患者富集"
       }
     ],
     "其它重要菌属": [
@@ -3470,10 +3524,205 @@
         "正常范围%": "0-5.7436",
         "人群水平%": "77%",
         "检出率%": "90.38%",
-        "说明": "说明:产气菌,与脂质代谢及心脑血管相关,过多可导致菌群紊乱,部分"
+        "说明": "说明:产气菌,与脂质代谢及心脑血管相关,过多可导致菌群紊乱,部分病原菌"
+      },
+      {
+        "名称": "嗜胆菌属 Bilophila",
+        "丰度%": "0.1352",
+        "正常范围%": "0-0.3348",
+        "人群水平%": "69%",
+        "检出率%": "66.83%",
+        "说明": "说明:条件致病菌,与耐胆汁酸和脂肪摄⼊相关,便秘⼈群丰度更⾼"
+      },
+      {
+        "名称": "Flavonifractor",
+        "丰度%": "0.0033",
+        "正常范围%": "0-0.415",
+        "人群水平%": "20%",
+        "检出率%": "91.83%",
+        "说明": "说明:参与肠道⼉茶素代谢,减轻免疫反应,产丁酸"
+      },
+      {
+        "名称": "Dorea菌属 Dorea",
+        "丰度%": "0.0501",
+        "正常范围%": "0.0144-2.49",
+        "人群水平%": "32%",
+        "检出率%": "89.42%",
+        "说明": "说明:消化碳水化合物,多发性硬化症、炎症性肠病、结直肠癌、自闭症谱系障碍以及肥胖⼈群中⾼丰度富集,"
+      },
+      {
+        "名称": "亨盖特氏菌属 Hungatella",
+        "丰度%": "0.1249",
+        "正常范围%": "0-0.8235",
+        "人群水平%": "64%",
+        "检出率%": "89.42%",
+        "说明": "说明:参与生成氧化三甲胺和牛磺酸。"
+      },
+      {
+        "名称": "颤螺菌属 Oscillospira",
+        "丰度%": "0.2999",
+        "正常范围%": "0.0126-0.8558",
+        "人群水平%": "81%",
+        "检出率%": "87.50%",
+        "说明": "说明:基石菌、核心菌群,帮助消化抗性淀粉,产丁酸,并在大肠中发酵。与⼉童过敏和肥胖呈负相关。"
+      },
+      {
+        "名称": "枸橼酸杆菌属 Citrobacter",
+        "丰度%": "ND",
+        "正常范围%": "0-0.0668",
+        "人群水平%": "37%",
+        "检出率%": "78.37%",
+        "说明": "说明:常⻅菌,免疫⼒下降可能引发感染。"
+      },
+      {
+        "名称": "Akkermansia",
+        "丰度%": "0.0135",
+        "正常范围%": "0.0018-7.8352",
+        "人群水平%": "49%",
+        "检出率%": "74.52%",
+        "说明": "说明:基石菌,可降解淀粉,黏蛋白降解菌,可控制体重,改善代谢和炎症,过多导致肠粘膜屏障破坏。"
+      },
+      {
+        "名称": "肠杆菌属 Enterobacter",
+        "丰度%": "0.0067",
+        "正常范围%": "0-0.083",
+        "人群水平%": "60%",
+        "检出率%": "63.46%",
+        "说明": "说明:产酸产气,不引起腹泻,机会性感染,过多导致菌群紊乱和肥胖。"
+      },
+      {
+        "名称": "苏黎世杆菌属 Turicibacter",
+        "丰度%": "0.0100",
+        "正常范围%": "0-0.2352",
+        "人群水平%": "73%",
+        "检出率%": "49.52%",
+        "说明": "说明:发酵生成乳酸,参与肌肉和疲劳调节。"
+      },
+      {
+        "名称": "丁酸弧菌属 Butyrivibrio",
+        "丰度%": "ND",
+        "正常范围%": "0-0.8134",
+        "人群水平%": "70%",
+        "检出率%": "35.58%",
+        "说明": "说明:利用纤维素、淀粉和其他多聚糖生成丁酸,有助于维持肠道上皮,发挥抗炎、抗氧化作用。可调节体内的氨水平,影响免疫。"
+      },
+      {
+        "名称": "克⾥斯滕森氏菌属 Christensenella",
+        "丰度%": "ND",
+        "正常范围%": "0-0.0072",
+        "人群水平%": "82%",
+        "检出率%": "5.77%",
+        "说明": "说明:过多:肥胖,代谢综合征,包括⾼血压、⾼血糖、异常胆固醇水平和腹部肥胖,胰岛素抵抗"
       }
     ],
-    "病原菌属": [],
-    "病原菌检出": []
+    "病原菌属": [
+      {
+        "名称": "嗜血杆菌属 Haemophilus",
+        "丰度%": "ND",
+        "正常范围%": "0-0.7752",
+        "人群水平%": "22%",
+        "检出率%": "94.23%",
+        "说明": "说明:病原菌,过多可导致菌群紊乱,可引发呼吸道感染,常⻅于呼吸道感染"
+      },
+      {
+        "名称": "沙⻔氏菌属 Salmonella",
+        "丰度%": "0.0236",
+        "正常范围%": "0-0.4104",
+        "人群水平%": "60%",
+        "检出率%": "87.98%",
+        "说明": "说明:是引起食物中毒和肠道感染的常⻅病原菌之⼀"
+      },
+      {
+        "名称": "萨特氏菌属 Sutterella",
+        "丰度%": "ND",
+        "正常范围%": "0-2.266",
+        "人群水平%": "21%",
+        "检出率%": "81.73%",
+        "说明": "说明:肠道共生菌,潜在病原菌,自闭症相关,减少IgA"
+      },
+      {
+        "名称": "棒杆菌属 Corynebacterium",
+        "丰度%": "ND",
+        "正常范围%": "0-0.2646",
+        "人群水平%": "99%",
+        "检出率%": "52.88%",
+        "说明": "说明:可导致急性腹泻、腹痛、恶心"
+      },
+      {
+        "名称": "气单胞菌属 Aeromonas",
+        "丰度%": "ND",
+        "正常范围%": "0-0.0334",
+        "人群水平%": "80%",
+        "检出率%": "29.33%",
+        "说明": "说明:病原菌"
+      },
+      {
+        "名称": "葡萄球菌属 Staphylococcus",
+        "丰度%": "ND",
+        "正常范围%": "0-0.0105",
+        "人群水平%": "78%",
+        "检出率%": "17.31%",
+        "说明": "说明:利用碳水化合物或氨基酸,产生乳酸。部分产生毒素,如金黄色葡萄球菌,可能引发肠道炎症、并影响肠道屏障功能"
+      },
+      {
+        "名称": "Vibrio",
+        "丰度%": "ND"
+      },
+      {
+        "名称": "99%",
+        "丰度%": "8.17%",
+        "说明": "说明:条件致病菌"
+      },
+      {
+        "名称": "沃氏嗜胆菌 Bilophila wadsworthia",
+        "丰度%": "0.135%",
+        "人群水平%": "69%",
+        "检出率%": "66.83%"
+      },
+      {
+        "名称": "肠炎⿏伤寒沙⻔氏菌 Salmonella enterica",
+        "丰度%": "0.024%",
+        "人群水平%": "60%",
+        "检出率%": "87.98%"
+      },
+      {
+        "名称": "大肠杆菌 Escherichia coli",
+        "丰度%": "0.020%",
+        "人群水平%": "10%",
+        "检出率%": "99.52%"
+      },
+      {
+        "名称": "脆弱拟杆菌 Bacteroides fragilis",
+        "丰度%": "0.020%",
+        "人群水平%": "23%",
+        "检出率%": "93.27%"
+      }
+    ],
+    "病原菌检出": [
+      {
+        "名称": "沃氏嗜胆菌 Bilophila wadsworthia",
+        "丰度%": "0.135%",
+        "人群水平%": "69%",
+        "检出率%": "66.83%"
+      },
+      {
+        "名称": "肠炎⿏伤寒沙⻔氏菌 Salmonella enterica",
+        "丰度%": "0.024%",
+        "人群水平%": "60%",
+        "检出率%": "87.98%"
+      },
+      {
+        "名称": "大肠杆菌 Escherichia coli",
+        "丰度%": "0.020%",
+        "人群水平%": "10%",
+        "检出率%": "99.52%"
+      },
+      {
+        "名称": "脆弱拟杆菌 Bacteroides fragilis",
+        "丰度%": "0.020%",
+        "人群水平%": "23%",
+        "检出率%": "93.27%"
+      }
+    ]
   }
 }

+ 76 - 9
docs/参考资料/extract_full_report_v5.py

@@ -356,7 +356,15 @@ def extract_all_triplet(all_lines):
         if all_lines[i] == '抗生素风险评估':
             j = i + 1
             abx_rows, _ = parse_triplet_until(all_lines[j:], ['抗生素耐药风险', '个体化食物推荐表'])
-            result['抗生素风险评估'] = abx_rows
+            # 去重:同名只保留第一条
+            seen = set()
+            deduped = []
+            for r in abx_rows:
+                n = r.get('名称', '')
+                if n and n not in seen:
+                    seen.add(n)
+                    deduped.append(r)
+            result['抗生素风险评估'] = deduped
             break
 
     return result
@@ -644,7 +652,7 @@ def extract_pathogens_inline(text):
 # ==========================================
 BACTERIA_TABLE_TITLES = [
     '核心菌属构成表', '益生菌', '有害菌属构成表',
-    '其它重要菌属构成表', '病原菌属构成表', '病原菌',
+    '其它重要菌属构成表', '病原菌属构成表',
 ]
 PHYLUM_TABLE_TITLES = ['菌门构成表', '菌群门水平构成表', '门水平菌群构成']
 CLASS_TABLE_TITLES = ['菌纲构成表', '菌群纲水平构成表', '纲水平菌群构成']
@@ -778,6 +786,13 @@ def _parse_bacteria_table(reader, pages_text, full_text, title, fmt, skip_header
     if sidx == -1:
         return results
 
+    # 病原菌检出表特殊处理:找"仅列出检出的病原菌"(跳过前面的说明文字中的"病原菌")
+    if title == '病原菌':
+        # 搜索更精确的表头
+        better_sidx = full_text.find('仅列出检出的病原菌')
+        if better_sidx != -1:
+            sidx = better_sidx
+
     # 找表格结束位置(下一个标题或页尾)
     end_pos = len(full_text)
     for t in BACTERIA_TABLE_TITLES + PHYLUM_TABLE_TITLES + CLASS_TABLE_TITLES + ORDER_TABLE_TITLES + FAMILY_TABLE_TITLES + GENUS_TABLE_TITLES + SPECIES_TABLE_TITLES + DISEASE_BACTERIA_TITLES + ['指标范围', '个体化食物推荐表', '报告总结', '健康总分']:
@@ -788,7 +803,13 @@ def _parse_bacteria_table(reader, pages_text, full_text, title, fmt, skip_header
 
     region = full_text[sidx:end_pos]
 
-    if fmt == 'triplet':
+    # 检测区域实际格式:如果换行数很少(<3)则是inline格式,即使全局fmt=triplet
+    lines_from_region = [l.strip() for l in region.split('\n') if l.strip()]
+    actual_fmt = fmt
+    if fmt == 'triplet' and len(lines_from_region) <= 5:
+        actual_fmt = 'inline'
+
+    if actual_fmt == 'triplet':
         # 三元组格式:每个字段单独一行
         lines = [l.strip() for l in region.split('\n') if l.strip()]
         # 找到数据开始的位置(跳过标题行)
@@ -859,12 +880,58 @@ def _parse_bacteria_table(reader, pages_text, full_text, title, fmt, skip_header
             else:
                 i += 1
     else:
-        # inline 格式:数据挤在一行且数字段无分隔符,无法可靠自动解析
-        # 见 朱评估报告 page 23-26,格式为 名称+丰度+范围+水平%+检出率% 无缝拼接
-        # 示例:梭菌属 Clostridium1.00450.0306-6.961566%99.52%
-        # 其中 1.00450.0306 无法区分 1.0045 + 0.0306 vs 1.004 + 50.0306
-        # 跳过自动提取,用户可参考 raw text
-        pass
+        # inline 格式:数据挤在一行,如 "嗜血杆菌属 Haemophilus ND 0-0.7752 22% 94.23% 说明:..."
+        # 适用于 pathogen 表、pathogen 检出表等 inline 格式嵌在 triplet PDF 中的情况
+        # 使用 re.finditer 扫描整段文本,不依赖换行分割
+        # 先清理标题行和说明文字
+        region_clean = region
+        for hdr in ['名称', '丰度%', '正常范围%', '处于人群%水平', '%正常人有检出', '人群水平%', '%人检出']:
+            region_clean = region_clean.replace(hdr, '')
+        # 移除说明文本(非数据行的说明段)
+        region_clean = re.sub(r'说明:[\u4e00-\u9fff\s,。、;:,.;:()()、/a-zA-Z0-9\-]{10,}?(?=[\u4e00-\u9fff]|$)', '', region_clean)
+        # 扫描所有匹配的数据行
+        # 模式1:中文名[(英文备注)] 英文名 丰度(ND/数字) 正常范围(可选) 人群水平% 检出率%
+        for m in re.finditer(
+            r'([\u4e00-\u9fff]{2,12}(?:[((][\u4e00-\u9fff\w]+[))])?)\s+'  # 中文名
+            r'(?:[A-Z][a-z]+(?:\s[A-Z][a-z]+)*\s+)?'  # 可选英文名
+            r'(ND|[\d]+\.?[\d]*%?)\s+'  # 丰度
+            r'([\d]+\.?[\d]*-[\d]+\.?[\d]*)?\s*'  # 可选正常范围
+            r'(\d+\.?\d*%?)\s+'  # 人群水平%
+            r'(\d+\.?\d*%)',  # 检出率%
+            region_clean):
+            name = m.group(1).strip()
+            pct = m.group(2)
+            if '病原菌' in name or '构成表' in name or '说明' in name or len(name) <= 1:
+                continue
+            normal_range = m.group(3) or ''
+            pop_level = m.group(4)
+            if not pop_level.endswith('%'):
+                pop_level += '%'
+            detection_rate = m.group(5)
+            entry = {'名称': name, '丰度%': pct}
+            if normal_range:
+                entry['正常范围%'] = normal_range
+            entry['人群水平%'] = pop_level
+            entry['检出率%'] = detection_rate
+            results.append(entry)
+        # 如果模式1没有匹配,尝试模式2:仅中文名+丰度+人群水平(+检出率)
+        if not results:
+            for m in re.finditer(
+                r'([\u4e00-\u9fff]{2,10}[\u4e00-\u9fff]?)\s+'
+                r'(ND|[\d]+\.?[\d]*%?)\s+'
+                r'(\d+\.?\d*%)\s+'
+                r'(\d+\.?\d*%)?',
+                region_clean):
+                name = m.group(1).strip()
+                pct = m.group(2)
+                if '病原菌' in name or '构成表' in name or '说明' in name or len(name) <= 1:
+                    continue
+                pop_level = m.group(3)
+                detection_rate = m.group(4) or ''
+                entry = {'名称': name, '丰度%': pct, '人群水平%': pop_level}
+                if detection_rate:
+                    entry['检出率%'] = detection_rate
+                results.append(entry)
 
     return results