#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 四库深度挖掘分析 — 呼吸系统/咳嗽哮喘主题 生成MD报告和JSON关联数据 """ import json import os import re import glob from collections import defaultdict, Counter # ============================================================ # 配置 # ============================================================ BASE_DIR = "/home/songyi/Documents/ai_agent_scraper_study/data/大医网" DISEASE_DIR = os.path.join(BASE_DIR, "01_来源数据", "疾病") PRESCRIPTION_DIR = os.path.join(BASE_DIR, "01_来源数据", "方剂") HERB_DIR = os.path.join(BASE_DIR, "01_来源数据", "中药材") ACUPOINT_DIR = os.path.join(BASE_DIR, "01_来源数据", "针灸穴位") OUTPUT_DIR_REPORT = os.path.join(BASE_DIR, "04_分析报告") OUTPUT_DIR_JSON = os.path.join(BASE_DIR, "03_关联融合", "交叉关联分析") MD_FILE = os.path.join(OUTPUT_DIR_REPORT, "咳嗽哮喘深度挖掘分析报告.md") JSON_FILE = os.path.join(OUTPUT_DIR_JSON, "咳嗽哮喘_关联数据.json") # 主题关键词定义(4层) KEYWORDS_CORE = ['咳嗽', '哮喘', '肺气虚', '肺阴虚', '风寒束肺', '风热犯肺', '痰热壅肺', '痰湿阻肺', '肺肾两虚', '肺燥', '肺热', '肺寒', '肺气不宣', '肺失宣降', '风邪犯肺'] KEYWORDS_SPECIALTY = ['支气管炎', '肺炎', '慢性阻塞性肺疾病', '哮喘', '感冒', '咽炎', '扁桃体炎', '鼻炎', '肺气肿', '肺结核', '支气管扩张', '上呼吸道感染', 'COPD', '慢阻肺', '肺纤维化', '肺结节'] KEYWORDS_SYMPTOM = ['咳嗽', '咳痰', '气喘', '咽痛', '发热', '鼻塞', '胸闷', '呼吸困难', '流涕', '喷嚏', '咽痒', '喉鸣', '气促', '咯血', '恶寒', '恶风', '喘息', '痰多'] KEYWORDS_TREATMENT = ['宣肺', '止咳', '化痰', '平喘', '清热', '润肺', '散寒', '清肺', '降气', '祛痰', '肃肺', '敛肺', '温肺', '疏风散寒', '疏风清热', '清热解毒', '滋阴润肺', '补肺益气', '化痰止咳'] # 权重 WEIGHT_CORE = 3 WEIGHT_SPECIALTY = 2 WEIGHT_SYMPTOM = 1 WEIGHT_TREATMENT = 1 # 阈值 THRESHOLD_DISEASE = 5.0 THRESHOLD_PRESCRIPTION = 5.0 THRESHOLD_HERB = 3.0 THRESHOLD_ACUPOINT = 5.0 # 药材分类关键词映射 HERB_CLASSIFICATION_MAP = [ # 化痰止咳平喘药 (['化痰', '止咳平喘', '化痰止咳', '止咳化痰', '化痰药', '止咳平喘药'], '化痰止咳平喘药'), # 清热药 (['清热', '清热解毒', '清热药', '清热泻火', '清热燥湿', '清热凉血', '清解'], '清热药'), # 解表药 (['解表', '发散风寒', '发散风热', '解表药', '发表'], '解表药'), # 补气药 (['补气', '益气', '补气药', '大补元气', '补脾益气', '补肺益气', '益气健脾'], '补气药'), # 滋阴药/补阴药 (['滋阴', '养阴', '补阴', '滋阴药', '养阴药', '补阴药', '润肺'], '滋阴药'), # 补血药 (['补血', '养血', '补血药'], '补血药'), # 补阳药 (['补阳', '壮阳', '补肾阳', '补阳药'], '补阳药'), # 理气药 (['理气', '行气', '理气药', '行气药', '疏肝理气', '破气'], '理气药'), # 活血化瘀药 (['活血', '化瘀', '活血化瘀', '活血药', '活血祛瘀', '破血', '散瘀'], '活血化瘀药'), # 温里药 (['温里', '温中', '散寒', '祛寒', '温里药', '温经', '温通'], '温里药'), # 祛风湿药 (['祛风湿', '祛风除湿', '祛风湿药'], '祛风湿药'), # 利水渗湿药 (['利水', '渗湿', '利尿', '利水渗湿', '利水消肿', '利尿通淋'], '利水渗湿药'), # 安神药 (['安神', '养心安神', '重镇安神', '安神药', '宁心安神'], '安神药'), # 平肝息风药 (['平肝', '息风', '平肝息风', '潜阳', '平肝潜阳', '息风止痉'], '平肝息风药'), # 开窍药 (['开窍', '开窍药', '醒神', '开窍醒神'], '开窍药'), # 收涩药 (['收涩', '固涩', '收敛', '固精', '止汗', '止泻', '收涩药'], '收涩药'), # 泻下药 (['泻下', '攻下', '润下', '峻下', '泻下药', '通便', '攻下'], '泻下药'), # 消食药 (['消食', '健胃消食', '消食药', '消积', '消食导滞'], '消食药'), # 止血药 (['止血', '止血药', '凉血止血', '收敛止血', '化瘀止血', '温经止血'], '止血药'), # 化湿药 (['化湿', '芳香化湿', '化湿药', '化湿和胃'], '化湿药'), # 驱虫药 (['驱虫', '杀虫', '驱虫药'], '驱虫药'), # 拔毒化腐生肌药 (['拔毒', '化腐', '生肌', '拔毒化腐'], '拔毒化腐生肌药'), # 涌吐药 (['涌吐', '涌吐药'], '涌吐药'), # 其他/未分类 ] # 药材分类补充映射 - 基于简介/功能中药名的分类 HERB_SPECIFIC_CLASSIFICATION = { '贝母': '化痰止咳平喘药', '川贝母': '化痰止咳平喘药', '浙贝母': '化痰止咳平喘药', '瓜蒌': '化痰止咳平喘药', '桔梗': '化痰止咳平喘药', '半夏': '化痰止咳平喘药', '天南星': '化痰止咳平喘药', '白前': '化痰止咳平喘药', '前胡': '化痰止咳平喘药', '旋覆花': '化痰止咳平喘药', '竹茹': '化痰止咳平喘药', '竹沥': '化痰止咳平喘药', '天竺黄': '化痰止咳平喘药', '海藻': '化痰止咳平喘药', '昆布': '化痰止咳平喘药', '杏仁': '化痰止咳平喘药', '苦杏仁': '化痰止咳平喘药', '紫苏子': '化痰止咳平喘药', '苏子': '化痰止咳平喘药', '葶苈子': '化痰止咳平喘药', '桑白皮': '化痰止咳平喘药', '款冬花': '化痰止咳平喘药', '紫菀': '化痰止咳平喘药', '枇杷叶': '化痰止咳平喘药', '马兜铃': '化痰止咳平喘药', '百部': '化痰止咳平喘药', '白果': '化痰止咳平喘药', '罗汉果': '化痰止咳平喘药', '矮地茶': '化痰止咳平喘药', '满山红': '化痰止咳平喘药', '银杏': '化痰止咳平喘药', '洋金花': '化痰止咳平喘药', '黄药子': '化痰止咳平喘药', '胖大海': '化痰止咳平喘药', '木蝴蝶': '化痰止咳平喘药', '青黛': '化痰止咳平喘药', '礞石': '化痰止咳平喘药', '蛤壳': '化痰止咳平喘药', '海浮石': '化痰止咳平喘药', '瓦楞子': '化痰止咳平喘药', '皂荚': '化痰止咳平喘药', '胆南星': '化痰止咳平喘药', '金荞麦': '化痰止咳平喘药', '黄芩': '清热药', '黄连': '清热药', '黄柏': '清热药', '金银花': '清热药', '连翘': '清热药', '板蓝根': '清热药', '大青叶': '清热药', '石膏': '清热药', '知母': '清热药', '栀子': '清热药', '夏枯草': '清热药', '龙胆': '清热药', '苦参': '清热药', '白鲜皮': '清热药', '蒲公英': '清热药', '鱼腥草': '清热药', '败酱草': '清热药', '穿心莲': '清热药', '牛黄': '清热药', '熊胆': '清热药', '赤芍': '清热药', '牡丹皮': '清热药', '紫草': '清热药', '玄参': '清热药', '生地黄': '清热药', '地骨皮': '清热药', '青蒿': '清热药', '白薇': '清热药', '胡黄连': '清热药', '银柴胡': '清热药', '射干': '清热药', '山豆根': '清热药', '马勃': '清热药', '秦皮': '清热药', '鸦胆子': '清热药', '白花蛇舌草': '清热药', '半边莲': '清热药', '山慈菇': '清热药', '土茯苓': '清热药', '芦根': '清热药', '天花粉': '清热药', '竹叶': '清热药', '淡竹叶': '清热药', '决明子': '清热药', '密蒙花': '清热药', '谷精草': '清热药', '麻黄': '解表药', '桂枝': '解表药', '紫苏': '解表药', '生姜': '解表药', '香薷': '解表药', '荆芥': '解表药', '防风': '解表药', '羌活': '解表药', '白芷': '解表药', '细辛': '解表药', '藁本': '解表药', '苍耳子': '解表药', '辛夷': '解表药', '薄荷': '解表药', '牛蒡子': '解表药', '蝉蜕': '解表药', '桑叶': '解表药', '菊花': '解表药', '葛根': '解表药', '柴胡': '解表药', '升麻': '解表药', '淡豆豉': '解表药', '浮萍': '解表药', '木贼': '解表药', '葱白': '解表药', '鹅不食草': '解表药', '人参': '补气药', '党参': '补气药', '黄芪': '补气药', '白术': '补气药', '甘草': '补气药', '山药': '补气药', '白扁豆': '补气药', '大枣': '补气药', '饴糖': '补气药', '蜂蜜': '补气药', '西洋参': '补气药', '太子参': '补气药', '沙参': '滋阴药', '北沙参': '滋阴药', '南沙参': '滋阴药', '麦冬': '滋阴药', '麦门冬': '滋阴药', '天门冬': '滋阴药', '天冬': '滋阴药', '玉竹': '滋阴药', '百合': '滋阴药', '石斛': '滋阴药', '黄精': '滋阴药', '枸杞子': '滋阴药', '墨旱莲': '滋阴药', '旱莲草': '滋阴药', '女贞子': '滋阴药', '桑椹': '滋阴药', '龟甲': '滋阴药', '鳖甲': '滋阴药', '黑芝麻': '滋阴药', '当归': '补血药', '熟地黄': '补血药', '白芍': '补血药', '何首乌': '补血药', '阿胶': '补血药', '龙眼肉': '补血药', '紫河车': '补血药', '鹿茸': '补阳药', '巴戟天': '补阳药', '淫羊藿': '补阳药', '仙茅': '补阳药', '杜仲': '补阳药', '续断': '补阳药', '狗脊': '补阳药', '补骨脂': '补阳药', '益智仁': '补阳药', '冬虫夏草': '补阳药', '蛤蚧': '补阳药', '菟丝子': '补阳药', '沙苑子': '补阳药', '韭菜子': '补阳药', '蛇床子': '补阳药', '海马': '补阳药', '海龙': '补阳药', '肉苁蓉': '补阳药', '锁阳': '补阳药', '核桃仁': '补阳药', '陈皮': '理气药', '橘皮': '理气药', '青皮': '理气药', '枳实': '理气药', '枳壳': '理气药', '木香': '理气药', '沉香': '理气药', '檀香': '理气药', '川楝子': '理气药', '乌药': '理气药', '荔枝核': '理气药', '佛手': '理气药', '香橼': '理气药', '玫瑰花': '理气药', '绿萼梅': '理气药', '薤白': '理气药', '大腹皮': '理气药', '柿蒂': '理气药', '刀豆': '理气药', '甘松': '理气药', '九香虫': '理气药', '丹参': '活血化瘀药', '川芎': '活血化瘀药', '延胡索': '活血化瘀药', '郁金': '活血化瘀药', '姜黄': '活血化瘀药', '乳香': '活血化瘀药', '没药': '活血化瘀药', '五灵脂': '活血化瘀药', '红花': '活血化瘀药', '桃仁': '活血化瘀药', '益母草': '活血化瘀药', '牛膝': '活血化瘀药', '鸡血藤': '活血化瘀药', '王不留行': '活血化瘀药', '穿山甲': '活血化瘀药', '土鳖虫': '活血化瘀药', '水蛭': '活血化瘀药', '虻虫': '活血化瘀药', '斑蝥': '活血化瘀药', '三棱': '活血化瘀药', '莪术': '活血化瘀药', '苏木': '活血化瘀药', '自然铜': '活血化瘀药', '血竭': '活血化瘀药', '儿茶': '活血化瘀药', '刘寄奴': '活血化瘀药', '干漆': '活血化瘀药', '附子': '温里药', '肉桂': '温里药', '干姜': '温里药', '吴茱萸': '温里药', '花椒': '温里药', '丁香': '温里药', '小茴香': '温里药', '高良姜': '温里药', '胡椒': '温里药', '荜茇': '温里药', '荜澄茄': '温里药', '独活': '祛风湿药', '威灵仙': '祛风湿药', '川乌': '祛风湿药', '蕲蛇': '祛风湿药', '乌梢蛇': '祛风湿药', '雷公藤': '祛风湿药', '木瓜': '祛风湿药', '蚕沙': '祛风湿药', '秦艽': '祛风湿药', '防己': '祛风湿药', '桑枝': '祛风湿药', '海桐皮': '祛风湿药', '海风藤': '祛风湿药', '五加皮': '祛风湿药', '狗脊': '祛风湿药', '桑寄生': '祛风湿药', '茯苓': '利水渗湿药', '猪苓': '利水渗湿药', '泽泻': '利水渗湿药', '薏苡仁': '利水渗湿药', '车前草': '利水渗湿药', '车前子': '利水渗湿药', '滑石': '利水渗湿药', '川木通': '利水渗湿药', '通草': '利水渗湿药', '瞿麦': '利水渗湿药', '萹蓄': '利水渗湿药', '地肤子': '利水渗湿药', '海金沙': '利水渗湿药', '石韦': '利水渗湿药', '冬葵子': '利水渗湿药', '灯心草': '利水渗湿药', '萆薢': '利水渗湿药', '茵陈': '利水渗湿药', '金钱草': '利水渗湿药', '虎杖': '利水渗湿药', '赤小豆': '利水渗湿药', '玉米须': '利水渗湿药', '酸枣仁': '安神药', '柏子仁': '安神药', '远志': '安神药', '合欢皮': '安神药', '夜交藤': '安神药', '龙骨': '安神药', '牡蛎': '安神药', '朱砂': '安神药', '磁石': '安神药', '琥珀': '安神药', '石决明': '平肝息风药', '珍珠母': '平肝息风药', '代赭石': '平肝息风药', '羚羊角': '平肝息风药', '钩藤': '平肝息风药', '天麻': '平肝息风药', '地龙': '平肝息风药', '全蝎': '平肝息风药', '蜈蚣': '平肝息风药', '僵蚕': '平肝息风药', '白蒺藜': '平肝息风药', '罗布麻': '平肝息风药', '麝香': '开窍药', '冰片': '开窍药', '苏合香': '开窍药', '石菖蒲': '开窍药', '山茱萸': '收涩药', '五味子': '收涩药', '乌梅': '收涩药', '诃子': '收涩药', '肉豆蔻': '收涩药', '赤石脂': '收涩药', '禹余粮': '收涩药', '莲子': '收涩药', '芡实': '收涩药', '金樱子': '收涩药', '覆盆子': '收涩药', '桑螵蛸': '收涩药', '海螵蛸': '收涩药', '浮小麦': '收涩药', '糯稻根须': '收涩药', '麻黄根': '收涩药', '罂粟壳': '收涩药', '椿皮': '收涩药', '鸡冠花': '收涩药', '大黄': '泻下药', '芒硝': '泻下药', '番泻叶': '泻下药', '芦荟': '泻下药', '火麻仁': '泻下药', '郁李仁': '泻下药', '松子仁': '泻下药', '甘遂': '泻下药', '大戟': '泻下药', '芫花': '泻下药', '商陆': '泻下药', '牵牛子': '泻下药', '巴豆': '泻下药', '山楂': '消食药', '神曲': '消食药', '麦芽': '消食药', '谷芽': '消食药', '稻芽': '消食药', '莱菔子': '消食药', '鸡内金': '消食药', '小蓟': '止血药', '大蓟': '止血药', '地榆': '止血药', '槐花': '止血药', '侧柏叶': '止血药', '白茅根': '止血药', '三七': '止血药', '茜草': '止血药', '蒲黄': '止血药', '花蕊石': '止血药', '降香': '止血药', '白及': '止血药', '仙鹤草': '止血药', '紫珠': '止血药', '棕榈炭': '止血药', '血余炭': '止血药', '藕节': '止血药', '艾叶': '止血药', '炮姜': '止血药', '灶心土': '止血药', '苍术': '化湿药', '厚朴': '化湿药', '广藿香': '化湿药', '佩兰': '化湿药', '砂仁': '化湿药', '白豆蔻': '化湿药', '草豆蔻': '化湿药', '草果': '化湿药', } # ============================================================ # 工具函数 # ============================================================ def flatten_text(data_dict): """将JSON所有字段展平为纯文本字符串""" texts = [] for key, value in data_dict.items(): if isinstance(value, dict): for k2, v2 in value.items(): if isinstance(v2, str): texts.append(v2) elif isinstance(v2, (list, tuple)): texts.extend([str(x) for x in v2]) elif isinstance(value, str): texts.append(value) elif isinstance(value, (list, tuple)): texts.extend([str(x) for x in value]) return ' '.join(texts) def load_all_json(directory): """加载目录下所有JSON文件""" records = [] files = sorted(glob.glob(os.path.join(directory, '*.json'))) for fpath in files: try: with open(fpath, 'r', encoding='utf-8') as f: data = json.load(f) records.append(data) except Exception as e: print(f" Warning: failed to load {fpath}: {e}") return records def score_record(record, keywords_core, keywords_specialty, keywords_symptom, keywords_treatment): """对一条记录进行评分""" text = flatten_text(record) total_score = 0 matched_details = {'core': [], 'specialty': [], 'symptom': [], 'treatment': []} # 核心证候 (+3) for kw in keywords_core: if kw in text: total_score += WEIGHT_CORE matched_details['core'].append(kw) # 专科疾病 (+2) for kw in keywords_specialty: if kw in text: total_score += WEIGHT_SPECIALTY matched_details['specialty'].append(kw) # 症状 (+1) for kw in keywords_symptom: if kw in text: total_score += WEIGHT_SYMPTOM matched_details['symptom'].append(kw) # 治法 (+1) for kw in keywords_treatment: if kw in text: total_score += WEIGHT_TREATMENT matched_details['treatment'].append(kw) return total_score, matched_details def classify_herb(record): """对药材进行TCM功能分类""" name = record.get('名称', '') if name in HERB_SPECIFIC_CLASSIFICATION: return HERB_SPECIFIC_CLASSIFICATION[name] # 从文本中查找分类关键词 text = flatten_text(record) # 先检查简介中的分类描述 intro = record.get('简介', '') for keywords, category in HERB_CLASSIFICATION_MAP: for kw in keywords: if kw in intro or kw in text: return category # 再检查功效作用 func = str(record.get('功效作用', {}).get('功能', '')) for keywords, category in HERB_CLASSIFICATION_MAP: for kw in keywords: if kw in func: return category # 检查性味归经 (归肺经等) meridian = record.get('性味归经', '') if '肺' in meridian and ('止咳' in text or '化痰' in text or '咳嗽' in text): return '化痰止咳平喘药' return '其他/未分类' def longest_prefix_match(herb_name, text): """检查药材名是否在文本中出现(支持最长前缀匹配)""" return herb_name in text def extract_herb_names_from_text(text, herb_names_sorted): """从文本中提取出现的药材名(使用最长前缀匹配)""" found = [] # 按长度降序排序,确保最长匹配优先 for hname in herb_names_sorted: if hname in text: found.append(hname) return found def build_cross_associations(diseases, prescriptions, herbs, acupoints, herb_names_sorted): """构建交叉关联""" assoc = { 'disease_prescription': [], 'disease_herb': [], 'prescription_herb': [], 'disease_acupoint': [], } # 疾病↔方剂(按主题关键词) # 已经通过评分关联,这里直接统计共同出现的主题关键词 for d in diseases: dname = d.get('名称', '') d_text = flatten_text(d) d_keywords = set() for kw in KEYWORDS_CORE + KEYWORDS_SPECIALTY + KEYWORDS_SYMPTOM + KEYWORDS_TREATMENT: if kw in d_text: d_keywords.add(kw) for p in prescriptions: pname = p.get('名称', '') p_text = flatten_text(p) common_kw = [kw for kw in d_keywords if kw in p_text] if common_kw: assoc['disease_prescription'].append({ 'disease': dname, 'prescription': pname, 'common_keywords': common_kw, 'score': len(common_kw) }) # 疾病↔药材(文本包含) for d in diseases: dname = d.get('名称', '') d_text = flatten_text(d) for h in herbs: hname = h.get('名称', '') if hname and hname in d_text: # Check if already exists if not any(a['disease'] == dname and a['herb'] == hname for a in assoc['disease_herb']): assoc['disease_herb'].append({ 'disease': dname, 'herb': hname }) # 方剂↔药材(方义/组成字段含药材名) for p in prescriptions: pname = p.get('名称', '') comp = p.get('方解-组成', '') fangyi = p.get('方义', '') p_text = comp + ' ' + fangyi # Also check other text for k, v in p.items(): if isinstance(v, str) and k != '名称': p_text += ' ' + v elif isinstance(v, dict): for v2 in v.values(): if isinstance(v2, str): p_text += ' ' + v2 found_herbs = set() for hname in herb_names_sorted: if hname in p_text: found_herbs.add(hname) for hname in found_herbs: assoc['prescription_herb'].append({ 'prescription': pname, 'herb': hname }) # 疾病↔穴位(主治字段匹配) for d in diseases: dname = d.get('名称', '') d_text = flatten_text(d) for a in acupoints: aname = a.get('名称', '') a_text = a.get('主治', '') + ' ' + a.get('详细主治', '') + ' ' + a.get('简介', '') # Check if disease keywords appear in acupoint text common = [] for kw in KEYWORDS_CORE + KEYWORDS_SPECIALTY + KEYWORDS_SYMPTOM + KEYWORDS_TREATMENT: if kw in a_text and kw in d_text: common.append(kw) if common: if not any(ad['disease'] == dname and ad['acupoint'] == aname for ad in assoc['disease_acupoint']): assoc['disease_acupoint'].append({ 'disease': dname, 'acupoint': aname, 'common_keywords': common, 'score': len(common) }) return assoc # ============================================================ # 主函数 # ============================================================ def main(): os.makedirs(OUTPUT_DIR_REPORT, exist_ok=True) os.makedirs(OUTPUT_DIR_JSON, exist_ok=True) print("=" * 60) print("呼吸系统/咳嗽哮喘 — 四库深度挖掘分析") print("=" * 60) # 1. 加载数据 print("\n[1/6] 加载四库数据...") diseases = load_all_json(DISEASE_DIR) prescriptions = load_all_json(PRESCRIPTION_DIR) herbs = load_all_json(HERB_DIR) acupoints = load_all_json(ACUPOINT_DIR) print(f" 疾病库: {len(diseases)} 条") print(f" 方剂库: {len(prescriptions)} 条") print(f" 中药材库: {len(herbs)} 条") print(f" 针灸穴位库: {len(acupoints)} 条") # 2. 评分 print("\n[2/6] 对四库数据进行主题评分...") # 疾病评分 disease_scores = [] for d in diseases: score, details = score_record(d, KEYWORDS_CORE, KEYWORDS_SPECIALTY, KEYWORDS_SYMPTOM, KEYWORDS_TREATMENT) if score >= THRESHOLD_DISEASE: disease_scores.append({ 'name': d.get('名称', '未知'), 'score': score, 'details': details, 'record': d }) disease_scores.sort(key=lambda x: x['score'], reverse=True) print(f" 疾病: 阈值≥{THRESHOLD_DISEASE}, 入选 {len(disease_scores)} 条") # 方剂评分 prescription_scores = [] for p in prescriptions: score, details = score_record(p, KEYWORDS_CORE, KEYWORDS_SPECIALTY, KEYWORDS_SYMPTOM, KEYWORDS_TREATMENT) if score >= THRESHOLD_PRESCRIPTION: prescription_scores.append({ 'name': p.get('名称', '未知'), 'score': score, 'details': details, 'record': p }) prescription_scores.sort(key=lambda x: x['score'], reverse=True) print(f" 方剂: 阈值≥{THRESHOLD_PRESCRIPTION}, 入选 {len(prescription_scores)} 条") # 药材评分 herb_scores = [] for h in herbs: score, details = score_record(h, KEYWORDS_CORE, KEYWORDS_SPECIALTY, KEYWORDS_SYMPTOM, KEYWORDS_TREATMENT) if score >= THRESHOLD_HERB: herb_scores.append({ 'name': h.get('名称', '未知'), 'score': score, 'details': details, 'record': h }) herb_scores.sort(key=lambda x: x['score'], reverse=True) print(f" 药材: 阈值≥{THRESHOLD_HERB}, 入选 {len(herb_scores)} 条") # 穴位评分 acupoint_scores = [] for a in acupoints: score, details = score_record(a, KEYWORDS_CORE, KEYWORDS_SPECIALTY, KEYWORDS_SYMPTOM, KEYWORDS_TREATMENT) if score >= THRESHOLD_ACUPOINT: acupoint_scores.append({ 'name': a.get('名称', '未知'), 'score': score, 'details': details, 'record': a }) acupoint_scores.sort(key=lambda x: x['score'], reverse=True) print(f" 穴位: 阈值≥{THRESHOLD_ACUPOINT}, 入选 {len(acupoint_scores)} 条") # 3. 药材分类 print("\n[3/6] 药材分类标注...") herb_classification = {} for hs in herb_scores: name = hs['name'] cls = classify_herb(hs['record']) herb_classification[name] = cls # 统计分类 class_counter = Counter(herb_classification.values()) print(f" 药材分类统计: {dict(class_counter.most_common())}") # 4. 交叉关联 print("\n[4/6] 构建交叉关联...") # 获取按长度降序排序的药材名列表(用于最长前缀匹配) all_herb_names = [h.get('名称', '') for h in herbs if h.get('名称', '')] herb_names_sorted = sorted(all_herb_names, key=lambda x: -len(x)) # 对于关联,使用所有入选的疾病和方剂,以及全部药材(含未入选的) all_herbs = herbs # 全部药材用于关联 assoc = build_cross_associations( [d['record'] for d in disease_scores], [p['record'] for p in prescription_scores], all_herbs, acupoints, herb_names_sorted ) print(f" 疾病↔方剂: {len(assoc['disease_prescription'])} 条") print(f" 疾病↔药材: {len(assoc['disease_herb'])} 条") print(f" 方剂↔药材: {len(assoc['prescription_herb'])} 条") print(f" 疾病↔穴位: {len(assoc['disease_acupoint'])} 条") # 5. 生成JSON关联数据 print("\n[5/6] 生成JSON关联数据...") json_data = { 'meta': { '主题': '呼吸系统/咳嗽哮喘', '生成时间': __import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '数据规模': { '疾病库': len(diseases), '方剂库': len(prescriptions), '中药材库': len(herbs), '针灸穴位库': len(acupoints) }, '阈值': { '疾病': THRESHOLD_DISEASE, '方剂': THRESHOLD_PRESCRIPTION, '药材': THRESHOLD_HERB, '穴位': THRESHOLD_ACUPOINT } }, 'scored_diseases': [ { 'name': d['name'], 'score': d['score'], 'matched': d['details'] } for d in disease_scores ], 'scored_prescriptions': [ { 'name': p['name'], 'score': p['score'], 'matched': p['details'] } for p in prescription_scores ], 'scored_herbs': [ { 'name': h['name'], 'score': h['score'], 'classification': herb_classification.get(h['name'], '其他/未分类'), 'matched': h['details'] } for h in herb_scores ], 'scored_acupoints': [ { 'name': a['name'], 'score': a['score'], 'matched': a['details'] } for a in acupoint_scores ], 'cross_associations': { 'disease_prescription': assoc['disease_prescription'], 'disease_herb': assoc['disease_herb'], 'prescription_herb': assoc['prescription_herb'], 'disease_acupoint': assoc['disease_acupoint'] }, 'herb_classification_summary': dict(class_counter.most_common()) } with open(JSON_FILE, 'w', encoding='utf-8') as f: json.dump(json_data, f, ensure_ascii=False, indent=2) print(f" JSON已保存至: {JSON_FILE}") # 6. 生成MD报告 print("\n[6/6] 生成MD分析报告...") # ---- 统计数据 ---- disease_top30 = disease_scores[:30] disease_other20 = disease_scores[30:50] if len(disease_scores) >= 50 else disease_scores[30:] presc_top30 = prescription_scores[:30] herb_top50 = herb_scores[:50] acu_top30 = acupoint_scores[:30] # 统计各类关键词出现频次 all_keyword_freq = Counter() for d in disease_scores: for cat in ['core', 'specialty', 'symptom', 'treatment']: for kw in d['details'][cat]: all_keyword_freq[kw] += 1 # 核心方剂药材列表 # 对方剂TOP30中每个方剂,列出其含有的药材 presc_herb_map = defaultdict(list) for ass in assoc['prescription_herb']: presc_herb_map[ass['prescription']].append(ass['herb']) # 经典配伍方案(TOP30穴位中常见的配伍) acu_combinations = [] for a in acupoint_scores[:30]: rec = a['record'] peiwu = rec.get('配伍', '') or rec.get('主要配伍', '') or '' if peiwu: acu_combinations.append({ 'acupoint': a['name'], 'combination': peiwu.strip() }) # ---- 构建MD ---- md_lines = [] md_lines.append(f"# 呼吸系统/咳嗽哮喘 四库深度挖掘分析报告\n") md_lines.append(f"> 生成时间: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") md_lines.append(f"> 数据来源: 大医网 · 疾病库(998条)、方剂库(1000条)、中药材库(1000条)、针灸穴位库(1000条)\n") md_lines.append(f"> 阈值设定: 疾病≥{THRESHOLD_DISEASE} | 方剂≥{THRESHOLD_PRESCRIPTION} | 药材≥{THRESHOLD_HERB} | 穴位≥{THRESHOLD_ACUPOINT}\n") md_lines.append("---\n") # 第一节:概览 md_lines.append("## 一、概览 — 四库统计表\n") md_lines.append("| 数据库 | 原始总数 | 入选数量 | 阈值 | 最高分 | 最低分 |") md_lines.append("|--------|---------|---------|------|--------|--------|") md_lines.append(f"| 疾病库 | {len(diseases)} | {len(disease_scores)} | ≥{THRESHOLD_DISEASE} | {disease_scores[0]['score'] if disease_scores else 0} | {disease_scores[-1]['score'] if disease_scores else 0} |") md_lines.append(f"| 方剂库 | {len(prescriptions)} | {len(prescription_scores)} | ≥{THRESHOLD_PRESCRIPTION} | {prescription_scores[0]['score'] if prescription_scores else 0} | {prescription_scores[-1]['score'] if prescription_scores else 0} |") md_lines.append(f"| 中药材库 | {len(herbs)} | {len(herb_scores)} | ≥{THRESHOLD_HERB} | {herb_scores[0]['score'] if herb_scores else 0} | {herb_scores[-1]['score'] if herb_scores else 0} |") md_lines.append(f"| 针灸穴位库 | {len(acupoints)} | {len(acupoint_scores)} | ≥{THRESHOLD_ACUPOINT} | {acupoint_scores[0]['score'] if acupoint_scores else 0} | {acupoint_scores[-1]['score'] if acupoint_scores else 0} |") md_lines.append("") # 关键词频次TOP md_lines.append("### 关键词匹配频次 TOP20\n") md_lines.append("| 关键词 | 匹配次数 | 权重级别 |") md_lines.append("|--------|---------|---------|") for kw, cnt in all_keyword_freq.most_common(20): if kw in KEYWORDS_CORE: level = "核心证候(+3)" elif kw in KEYWORDS_SPECIALTY: level = "专科疾病(+2)" elif kw in KEYWORDS_SYMPTOM: level = "症状(+1)" else: level = "治法(+1)" md_lines.append(f"| {kw} | {cnt} | {level} |") md_lines.append("") # 第二节:相关疾病 md_lines.append("## 二、相关疾病分析\n") md_lines.append("### 2.1 TOP30 核心相关疾病\n") md_lines.append("| 排名 | 疾病名称 | 综合评分 | 核心证候 | 专科疾病 | 症状 | 治法 | 关键词数 |") md_lines.append("|------|---------|---------|---------|---------|------|------|---------|") for i, d in enumerate(disease_top30[:30], 1): det = d['details'] core_str = '、'.join(det['core'][:3]) + ('...' if len(det['core']) > 3 else '') spec_str = '、'.join(det['specialty'][:3]) + ('...' if len(det['specialty']) > 3 else '') symp_str = '、'.join(det['symptom'][:3]) + ('...' if len(det['symptom']) > 3 else '') treat_str = '、'.join(det['treatment'][:3]) + ('...' if len(det['treatment']) > 3 else '') total_kw = len(det['core']) + len(det['specialty']) + len(det['symptom']) + len(det['treatment']) md_lines.append(f"| {i} | {d['name']} | {d['score']} | {core_str} | {spec_str} | {symp_str} | {treat_str} | {total_kw} |") md_lines.append("") if disease_other20: md_lines.append("### 2.2 其他相关疾病(TOP21-50)\n") md_lines.append("| 排名 | 疾病名称 | 综合评分 | 关键词数 |") md_lines.append("|------|---------|---------|---------|") for i, d in enumerate(disease_other20, 21): det = d['details'] total_kw = len(det['core']) + len(det['specialty']) + len(det['symptom']) + len(det['treatment']) md_lines.append(f"| {i} | {d['name']} | {d['score']} | {total_kw} |") md_lines.append("") # 第三节:方剂深度挖掘 md_lines.append("## 三、方剂深度挖掘\n") md_lines.append("### 3.1 TOP30 高频相关方剂\n") md_lines.append("| 排名 | 方剂名称 | 综合评分 | 核心证候 | 专科疾病 | 症状 | 治法 | 关键词数 |") md_lines.append("|------|---------|---------|---------|---------|------|------|---------|") for i, p in enumerate(presc_top30, 1): det = p['details'] core_str = '、'.join(det['core'][:3]) + ('...' if len(det['core']) > 3 else '') spec_str = '、'.join(det['specialty'][:3]) + ('...' if len(det['specialty']) > 3 else '') symp_str = '、'.join(det['symptom'][:3]) + ('...' if len(det['symptom']) > 3 else '') treat_str = '、'.join(det['treatment'][:3]) + ('...' if len(det['treatment']) > 3 else '') total_kw = len(det['core']) + len(det['specialty']) + len(det['symptom']) + len(det['treatment']) md_lines.append(f"| {i} | {p['name']} | {p['score']} | {core_str} | {spec_str} | {symp_str} | {treat_str} | {total_kw} |") md_lines.append("") md_lines.append("### 3.2 核心方剂药材组成\n") md_lines.append("以下列出TOP30方剂的主要药材成分(基于方剂组成及方义文本提取):\n") md_lines.append("| 方剂名称 | 所含药材 | 药材数量 |") md_lines.append("|---------|---------|---------|") for p in presc_top30: pname = p['name'] herbs_in_presc = presc_herb_map.get(pname, []) if herbs_in_presc: herb_str = '、'.join(herbs_in_presc[:8]) if len(herbs_in_presc) > 8: herb_str += '...' md_lines.append(f"| {pname} | {herb_str} | {len(herbs_in_presc)} |") else: md_lines.append(f"| {pname} | - | 0 |") md_lines.append("") # 第四节:核心药材 md_lines.append("## 四、核心药材分析\n") md_lines.append("### 4.1 TOP50 核心相关药材\n") md_lines.append("| 排名 | 药材名称 | 综合评分 | 功效分类 | 核心证候 | 专科疾病 | 症状 | 治法 |") md_lines.append("|------|---------|---------|---------|---------|---------|------|------|") for i, h in enumerate(herb_top50, 1): det = h['details'] cls = herb_classification.get(h['name'], '其他/未分类') core_str = '、'.join(det['core'][:3]) + ('...' if len(det['core']) > 3 else '') spec_str = '、'.join(det['specialty'][:3]) + ('...' if len(det['specialty']) > 3 else '') symp_str = '、'.join(det['symptom'][:3]) + ('...' if len(det['symptom']) > 3 else '') treat_str = '、'.join(det['treatment'][:3]) + ('...' if len(det['treatment']) > 3 else '') md_lines.append(f"| {i} | {h['name']} | {h['score']} | {cls} | {core_str} | {spec_str} | {symp_str} | {treat_str} |") md_lines.append("") md_lines.append("### 4.2 药材功效分类汇总\n") md_lines.append("| 功效分类 | 药材数量 | 代表性药材 |") md_lines.append("|---------|---------|-----------|") for cls_name, count in class_counter.most_common(): herbs_in_cls = [h['name'] for h in herb_scores if herb_classification.get(h['name'], '其他/未分类') == cls_name] rep_herbs = '、'.join(herbs_in_cls[:5]) md_lines.append(f"| {cls_name} | {count} | {rep_herbs} |") md_lines.append("") # 第五节:针灸穴位 md_lines.append("## 五、针灸穴位分析\n") md_lines.append("### 5.1 TOP30 相关穴位\n") md_lines.append("| 排名 | 穴位名称 | 综合评分 | 隶属 | 核心证候 | 症状 | 治法 |") md_lines.append("|------|---------|---------|------|---------|------|------|") for i, a in enumerate(acu_top30, 1): rec = a['record'] det = a['details'] belong = rec.get('隶属', '') core_str = '、'.join(det['core'][:3]) + ('...' if len(det['core']) > 3 else '') symp_str = '、'.join(det['symptom'][:3]) + ('...' if len(det['symptom']) > 3 else '') treat_str = '、'.join(det['treatment'][:3]) + ('...' if len(det['treatment']) > 3 else '') md_lines.append(f"| {i} | {a['name']} | {a['score']} | {belong} | {core_str} | {symp_str} | {treat_str} |") md_lines.append("") md_lines.append("### 5.2 经典配伍方案\n") md_lines.append("以下为相关穴位的经典配伍方案:\n") md_lines.append("| 穴位 | 配伍方案 |") md_lines.append("|------|---------|") for ac in acu_combinations: md_lines.append(f"| {ac['acupoint']} | {ac['combination'][:100]} |") md_lines.append("") # 第六节:结论与临床建议 md_lines.append("## 六、结论与临床建议\n") # 病机特征分析 md_lines.append("### 6.1 病机特征分析\n") # 从评分数据中提取高频病机 core_freq = Counter() for d in disease_scores: for kw in d['details']['core']: core_freq[kw] += 1 for p in prescription_scores: for kw in p['details']['core']: core_freq[kw] += 1 top_core = core_freq.most_common(10) md_lines.append("基于四库数据分析,呼吸系统/咳嗽哮喘相关病证的核心病机特征如下:\n") md_lines.append(f"- **高频证候**: {'、'.join([f'{kw}({cnt}次)' for kw, cnt in top_core])}") md_lines.append("- **病位特点**: 病位主要在肺,涉及肾、脾二脏。肺为娇脏,主气司呼吸,外合皮毛,开窍于鼻,易受外邪侵袭。") md_lines.append("- **病性特点**: 多虚实夹杂,急性期以邪实(风寒、风热、痰热、痰湿)为主,慢性期以本虚(肺气虚、肺阴虚、肺肾两虚)为主。") md_lines.append("- **传变规律**: 外邪犯肺→肺失宣降→咳嗽气喘→久病及肾→肺肾两虚。") md_lines.append("") # 用药规律分析 md_lines.append("### 6.2 用药规律分析\n") md_lines.append(f"**药材功效分类分布**:\n") for cls_name, count in class_counter.most_common(8): pct = count / len(herb_scores) * 100 if herb_scores else 0 md_lines.append(f"- **{cls_name}**: {count}味 ({pct:.1f}%)") md_lines.append("") md_lines.append("**核心用药规律**:\n") # 提取高频药材 top_herb_names = [h['name'] for h in herb_scores[:20]] top_herb_types = Counter() for hn in top_herb_names: cls = herb_classification.get(hn, '其他/未分类') top_herb_types[cls] += 1 md_lines.append(f"1. **化痰止咳平喘药为君**: TOP20药材中{'、'.join([f'{k}({v}味)' for k,v in top_herb_types.most_common()])},体现了\"咳喘必化痰\"的治疗原则。") md_lines.append(f"2. **宣肺与降气并用**: 高频药材中兼有宣肺散邪(麻黄、桔梗)与降气平喘(杏仁、苏子、葶苈子)之品,体现宣降相因的治法。") md_lines.append(f"3. **清热与温散并举**: 根据寒热辨证,热证选黄芩、桑白皮等清热药,寒证选麻黄、细辛、干姜等温散药。") md_lines.append(f"4. **补泻兼施**: 慢性咳喘多配补气药(黄芪、党参、甘草)、滋阴药(麦冬、沙参、百合)以扶正固本。") md_lines.append("") # 分类方剂推荐 md_lines.append("### 6.3 方剂推荐\n") md_lines.append("根据辨证分型推荐以下方剂:\n") # 从入选方剂中分类 def find_presc_by_keyword(kw_list, presc_list): found = [] for p in presc_list: p_text = flatten_text(p['record']) for kw in kw_list: if kw in p_text: found.append(p['name']) break return found[:5] feng_han = find_presc_by_keyword(['风寒束肺', '风寒', '散寒'], prescription_scores) feng_re = find_presc_by_keyword(['风热犯肺', '风热', '疏风清热'], prescription_scores) tan_re = find_presc_by_keyword(['痰热壅肺', '痰热', '清肺化痰'], prescription_scores) tan_shi = find_presc_by_keyword(['痰湿阻肺', '痰湿', '燥湿化痰'], prescription_scores) fei_yin = find_presc_by_keyword(['肺阴虚', '阴虚', '滋阴润肺'], prescription_scores) fei_qi = find_presc_by_keyword(['肺气虚', '肺肾两虚', '补肺益气'], prescription_scores) fei_zao = find_presc_by_keyword(['肺燥', '润肺'], prescription_scores) md_lines.append("| 证型 | 推荐方剂 |") md_lines.append("|------|---------|") if feng_han: md_lines.append(f"| 风寒束肺证 | {'、'.join(feng_han)} |") if feng_re: md_lines.append(f"| 风热犯肺证 | {'、'.join(feng_re)} |") if tan_re: md_lines.append(f"| 痰热壅肺证 | {'、'.join(tan_re)} |") if tan_shi: md_lines.append(f"| 痰湿阻肺证 | {'、'.join(tan_shi)} |") if fei_zao: md_lines.append(f"| 肺燥咳嗽证 | {'、'.join(fei_zao)} |") if fei_yin: md_lines.append(f"| 肺阴虚证 | {'、'.join(fei_yin)} |") if fei_qi: md_lines.append(f"| 肺气虚/肺肾两虚证 | {'、'.join(fei_qi)} |") md_lines.append("") # 第七节:日常调理建议 md_lines.append("## 七、日常调理建议\n") md_lines.append("### 7.1 饮食调理\n") md_lines.append("1. **宜食润肺食物**: 梨、百合、银耳、山药、蜂蜜、白萝卜、荸荠等,有润肺生津之效。") md_lines.append("2. **辨证食疗**:") md_lines.append(" - 风寒咳嗽:生姜红糖水、葱白粥,以散寒宣肺。") md_lines.append(" - 风热咳嗽:桑叶菊花茶、梨皮萝卜汤,以疏风清热。") md_lines.append(" - 痰湿咳嗽:陈皮薏米粥、茯苓山药汤,以健脾化痰。") md_lines.append(" - 阴虚咳嗽:沙参麦冬汤、百合银耳羹,以滋阴润肺。") md_lines.append("3. **忌口注意**: 忌辛辣刺激、生冷油腻、海鲜发物等易生痰助湿之品;戒烟酒。") md_lines.append("") md_lines.append("### 7.2 日常作息\n") md_lines.append("1. **起居有常**: 规律作息,避免熬夜(熬夜伤阴,肺阴更虚)。") md_lines.append("2. **防寒保暖**: 注意气候变化,适时增减衣物,尤其注意背部和颈部的保暖。") md_lines.append("3. **室内环境**: 保持居室空气流通,湿度适宜(50-60%),避免干燥空气刺激呼吸道。") md_lines.append("4. **佩戴口罩**: 雾霾天气或花粉季外出佩戴口罩,减少呼吸道刺激。") md_lines.append("") md_lines.append("### 7.3 运动保健\n") md_lines.append("1. **呼吸锻炼**: 练习腹式呼吸、缩唇呼吸,增强膈肌力量,改善肺通气功能。") md_lines.append("2. **养生功法**: 太极拳、八段锦、五禽戏等传统功法,有助调节呼吸、增强体质。") md_lines.append("3. **适度有氧**: 散步、慢跑、游泳等有氧运动,循序渐进,量力而行。") md_lines.append("4. **穴位按摩**: 每日按摩肺俞、定喘、膻中、足三里等穴,每次3-5分钟,以酸胀为度。") md_lines.append("5. **注意事项**: 急性发作期避免剧烈运动,以休息为主。") md_lines.append("") # 第八节:附录 md_lines.append("## 八、附录 — 关联数据文件清单\n") md_lines.append("| 文件名称 | 路径 | 说明 |") md_lines.append("|---------|------|------|") md_lines.append(f"| 咳嗽哮喘深度挖掘分析报告.md | {MD_FILE} | 本报告(MD格式) |") md_lines.append(f"| 咳嗽哮喘_关联数据.json | {JSON_FILE} | 四库评分数据及交叉关联(JSON格式) |") md_lines.append("") md_lines.append("### JSON关联数据字段说明\n") md_lines.append("| 字段路径 | 类型 | 说明 |") md_lines.append("|---------|------|------|") md_lines.append("| `meta` | dict | 元数据(主题、时间、数据规模、阈值) |") md_lines.append("| `scored_diseases` | list | 入选疾病列表(含名称、评分、匹配详情) |") md_lines.append("| `scored_prescriptions` | list | 入选方剂列表 |") md_lines.append("| `scored_herbs` | list | 入选药材列表(含功效分类) |") md_lines.append("| `scored_acupoints` | list | 入选穴位列表 |") md_lines.append("| `cross_associations.disease_prescription` | list | 疾病↔方剂关联 |") md_lines.append("| `cross_associations.disease_herb` | list | 疾病↔药材关联 |") md_lines.append("| `cross_associations.prescription_herb` | list | 方剂↔药材关联 |") md_lines.append("| `cross_associations.disease_acupoint` | list | 疾病↔穴位关联 |") md_lines.append("| `herb_classification_summary` | dict | 药材功效分类统计 |") md_lines.append("") md_content = '\n'.join(md_lines) with open(MD_FILE, 'w', encoding='utf-8') as f: f.write(md_content) print(f" MD报告已保存至: {MD_FILE}") # ===== 验证 ===== print("\n" + "=" * 60) print("分析完成!") print("=" * 60) print(f"\n输出文件:") print(f" 1. MD报告: {MD_FILE}") print(f" 2. JSON数据: {JSON_FILE}") print(f"\n各库入选数量:") print(f" 疾病: {len(disease_scores)} 条") print(f" 方剂: {len(prescription_scores)} 条") print(f" 药材: {len(herb_scores)} 条") print(f" 穴位: {len(acupoint_scores)} 条") print(f"\n交叉关联:") print(f" 疾病↔方剂: {len(assoc['disease_prescription'])} 条") print(f" 疾病↔药材: {len(assoc['disease_herb'])} 条") print(f" 方剂↔药材: {len(assoc['prescription_herb'])} 条") print(f" 疾病↔穴位: {len(assoc['disease_acupoint'])} 条") if __name__ == '__main__': main()