初始归档:健康管理资料库(大医网/药膳/体质监测/中医理论等12个资料集,7712个文件)

This commit is contained in:
512song committed 2026-09-23 21:59:25 +08:00
commit 80ae3811cf
7712 files changed
+4628547

No files matched your search

@@ -0,0 +1,311 @@
#!/usr/bin/env python3
"""药膳食疗 × 中药材 深度关联分析"""
import json, os, glob, re
from collections import Counter, defaultdict
TOP_DIR = "/home/songyi/Documents/ai_agent_scraper_study/data/大医网/"
DY_DIR = os.path.join(TOP_DIR, "药膳食疗/")
ZY_DIR = os.path.join(TOP_DIR, "中药材/")
# ===================== 加载数据 =====================
print("加载药膳食疗库...")
all_diets = []
for f in glob.glob(os.path.join(DY_DIR, "*.json")):
with open(f, encoding='utf-8') as fh:
all_diets.append(json.load(fh))
print("加载中药材库...")
all_herbs = {}
herb_aliases = defaultdict(set) # 别名→标准名
for f in glob.glob(os.path.join(ZY_DIR, "*.json")):
with open(f, encoding='utf-8') as fh:
h = json.load(fh)
name = h.get('名称', '')
all_herbs[name] = h
for alias in str(h.get('别名', '')).split('、'):
a = alias.strip()
if a:
herb_aliases[a].add(name)
print(f"药膳: {len(all_diets)} 条 | 药材: {len(all_herbs)} 条 | 别名映射: {len(herb_aliases)} 组\n")
# ===================== 药材标准化匹配 =====================
# 合并药材名+别名集合,按长度排序(最长优先)
all_herb_names = sorted(set(all_herbs.keys()), key=lambda x: -len(x))
# 别名去标准名重复
pure_aliases = []
for alias, targets in herb_aliases.items():
if alias not in all_herbs:
pure_aliases.append((alias, targets))
# 按长度降序
pure_aliases.sort(key=lambda x: -len(x[0]))
def match_herbs(text):
"""从文本中匹配药材(标准名优先,别名次之)"""
found = set()
for name in all_herb_names:
if len(name) >= 2 and name in text:
found.add(name)
for alias, targets in pure_aliases:
if len(alias) >= 2 and alias in text:
found.update(targets)
return found
# ===================== Step 1: 药材频次与覆盖分析 =====================
print("=" * 60)
print("Step 1: 药材使用频次与覆盖度分析")
print("=" * 60)
herb_in_diet_count = Counter()
herb_diet_pairs = defaultdict(list) # 药材→使用该药材的药膳列表
for diet in all_diets:
pei_fang = diet.get('配方', '')
matched = match_herbs(pei_fang)
for h in matched:
herb_in_diet_count[h] += 1
herb_diet_pairs[h].append(diet['名称'])
used_herb_count = len(herb_in_diet_count)
coverage = used_herb_count / len(all_herbs) * 100
print(f"\n药材库总数: {len(all_herbs)}")
print(f"在药膳中出现: {used_herb_count} ({coverage:.1f}%)")
print(f"未出现在药膳中: {len(all_herbs) - used_herb_count}")
print(f"\n>>> TOP 30 高频药材 <<<")
for herb, cnt in herb_in_diet_count.most_common(30):
# 获取药材功效(字段名是'功能')
h_data = all_herbs.get(herb, {})
gongxiao = ""
if isinstance(h_data.get('功效作用'), dict):
gongxiao = h_data['功效作用'].get('功能', '')
else:
gongxiao = str(h_data.get('功效作用', ''))
gongxiao_short = (gongxiao[:30] + '..') if len(gongxiao) > 30 else gongxiao
print(f" {herb:6s}: {cnt:3d}次 | 药材功效: {gongxiao_short}")
# ===================== Step 2: 双向映射 =====================
print(f"\n{'=' * 60}")
print("Step 2: 药膳-药材双向映射")
print("=" * 60)
# 药膳→药材映射
diet_to_herbs = {}
for diet in all_diets:
pei_fang = diet.get('配方', '')
matched = match_herbs(pei_fang)
diet_to_herbs[diet['名称']] = matched
# 药材→药膳 已在上一步构建
# 每味药材关联的药膳数量分布
pair_dist = Counter()
for herb, diets in herb_diet_pairs.items():
pair_dist[len(diets)] += 1
print(f"\n药材→药膳关联数分布:")
for k in sorted(pair_dist.keys())[:10]:
print(f" 关联{k}个药膳: {pair_dist[k]}味药材")
if len(pair_dist) > 10:
tail_sum = sum(v for k, v in pair_dist.items() if k > 10)
print(f" 关��>10个药膳: {tail_sum}味药材")
# 药膳→药材关联数分布
diet_herb_dist = Counter()
for diet_name, herbs in diet_to_herbs.items():
diet_herb_dist[len(herbs)] += 1
print(f"\n药膳→药材关联数分布:")
for k in sorted(diet_herb_dist.keys())[:8]:
print(f" 含{k}味药材: {diet_herb_dist[k]}个药膳")
if len(diet_herb_dist) > 8:
tail_sum = sum(v for k, v in diet_herb_dist.items() if k > 8)
print(f" 含>8味药材: {tail_sum}个药膳")
# 核心枢纽药材(同时出现在药膳和药材库,且频次最高的)
hub_herbs = []
for herb, cnt in herb_in_diet_count.most_common(10):
h_data = all_herbs[herb]
gx = str(h_data.get('功效作用', ''))
hub_herbs.append((herb, cnt, gx))
print(f"\n>>> 10大枢纽药材 <<<")
for herb, cnt, gx in hub_herbs:
print(f" {herb}: 出现{cnt}次, 药材功效: {str(gx)[:50]}")
# ===================== Step 3: 功效交叉验证 =====================
print(f"\n{'=' * 60}")
print("Step 3: 功效交叉验证分析")
print("=" * 60)
# 提取药膳功效标签
diet_gx_labels = []
for diet in all_diets:
gx = diet.get('功效', '')
diet_gx_labels.append((diet['名称'], gx))
# 提取药材功效标签
herb_gx_labels = {}
for name, hdata in all_herbs.items():
gx = str(hdata.get('功效作用', ''))
herb_gx_labels[name] = gx
# 药膳功效大类分布
gx_categories = Counter()
GX_CAT_MAP = {
'补气': '补益', '补血': '补益', '补阴': '补益', '滋阴': '补益', '补肾': '补益',
'补脾': '补益', '健脾': '补益', '补肝': '补益', '益精': '补益', '壮阳': '补益',
'温阳': '补益', '扶正': '补益', '养心': '补益', '养阴': '补益', '益气': '补益',
'清热': '清热', '解毒': '清热', '泻火': '清热', '凉血': '清热', '滋阴': '滋阴',
'活血': '活血', '化瘀': '活血', '祛瘀': '活血', '行气': '理气', '理气': '理气',
'止痛': '止痛', '安神': '安神', '止咳': '止咳化痰', '化痰': '止咳化痰', '润肺': '止咳化痰',
'祛风': '祛风除湿', '除湿': '祛风除湿', '散寒': '散寒解表', '解表': '散寒解表',
'利水': '利水渗湿', '通便': '通淋', '明目': '明目'
}
for diet_name, gx_text in diet_gx_labels:
matched_cats = set()
for kw, cat in GX_CAT_MAP.items():
if kw in gx_text:
matched_cats.add(cat)
if not matched_cats:
matched_cats.add('其他')
gx_categories.update(matched_cats)
print(f"\n药膳功效大类分布:")
for cat, cnt in gx_categories.most_common():
print(f" {cat}: {cnt}条 ({cnt/len(all_diets)*100:.1f}%)")
# 交叉验证:药膳功效 vs 组成药材功效一致性
# 检查药膳功效描述中的关键词是否在药材功效中也有体现
consistency_count = 0
total_checked = 0
for diet in all_diets:
diet_name = diet['名称']
diet_gx = diet.get('功效', '')
herbs_used = diet_to_herbs.get(diet_name, set())
if not herbs_used:
continue
# 提取药膳功效中的 2-3 字词
gx_words = re.findall(r'[\.。,.、,]*(.{2,3})[\.。,.、,]?', diet_gx)
if not gx_words:
gx_words = [diet_gx[:4]] # fallback
# 检查药材功效是否包含相同关键词
consistent_words = 0
for word in gx_words:
if len(word) < 2:
continue
for h_name in herbs_used:
h_gx = herb_gx_labels.get(h_name, '')
if word in h_gx:
consistent_words += 1
break # 只要有一个药材匹配就算
total_checked += 1
if consistent_words > 0:
consistency_count += 1
consistency_pct = consistency_count / total_checked * 100 if total_checked > 0 else 0
print(f"\n功效一致性验证:")
print(f" 参与验证药膳: {total_checked}")
print(f" 功效可追溯至组成药材: {consistency_count} ({consistency_pct:.1f}%)")
# ===================== Step 4: 特殊分析 — 药食同源药材统计 =====================
print(f"\n{'='*60}")
print("Step 4: 药食同源药材深度分析")
print("="*60)
# 常见药食同源药材名单(国家卫健委公布的)
med_food_herbs = {
'山药', '枸杞子', '枸杞', '茯苓', '甘草', '生姜', '大枣', '红枣',
'薏苡仁', '百合', '桂圆肉', '山楂', '陈皮', '菊花', '蜂蜜', '花椒',
'丁香', '八角茴香', '小茴香', '胡椒', '砂仁', '肉桂', '八角',
'杏仁', '核桃仁', '桃仁', '莲子', '芡实', '白果', '桑葚', '黑芝麻',
'黑芝麻', '黑芝麻', '黑豆', '黄豆', '黑芝麻', '黑芝麻', '黑芝麻',
'地黄', '玉竹', '黄精', '决明子', '罗汉果', '桑叶', '洛神花',
'蜂蜜', '党参', '黄芪', '红枣', '当归', '何首乌', '杜仲', '骨碎补',
'白果', '核桃', '杏仁', '桃仁', '花椒', '胡椒', '香薷', '高良姜',
'砂仁', '肉桂', '草果', '白芷', '白豆蔻', '肉豆蔻', '草豆蔻',
'紫苏', '薄荷', '胖大海', '鱼腥草', '姜黄', '荜澄茄', '青果', '橘皮',
'罗汉果', '乌梅', '陈皮', '大枣', '甘草', '丁香', '八角茴香', '山奈',
'阴香', '草果', '肉蔻', '草豆蔻', '砂仁', '白豆蔻', '肉豆蔻', '高良姜',
'香薷', '花椒', '小茴香', '八角', '桂花'
}
# 统计药食同源药材在药膳中的使用
yf_usage = Counter()
for diet in all_diets:
pei_fang = diet.get('配方', '')
for hname in med_food_herbs:
if hname in pei_fang and hname in herb_in_diet_count:
yf_usage[hname] += 1
print(f"\n药食同源药材使用 TOP 15:")
for herb, cnt in yf_usage.most_common(15):
print(f" {herb}: {cnt}次")
non_yf = herb_in_diet_count - yf_usage
print(f"\n非药食同源药材使用 TOP 10:")
for herb, cnt in non_yf.most_common(10):
print(f" {herb}: {cnt}次")
# ===================== Step 5: 药膳配伍规律分析 =====================
print(f"\n{'='*60}")
print("Step 5: 药膳配伍规律分析")
print("="*60)
# 药材对共现分析
herb_pair_freq = Counter()
for diet in all_diets:
pei_fang = diet.get('配方', '')
herbs = match_herbs(pei_fang)
herb_list = sorted(list(herbs))
for i in range(len(herb_list)):
for j in range(i+1, len(herb_list)):
pair = (herb_list[i], herb_list[j])
herb_pair_freq[pair] += 1
print(f"\n药材共现TOP 15:")
for (h1, h2), cnt in herb_pair_freq.most_common(15):
print(f" {h1}+{h2}: {cnt}次")
# ===================== 保存索引 =====================
# 双向映射索引
bidirectional = {
"药膳→药材": {name: sorted(list(herbs)) for name, herbs in diet_to_herbs.items()},
"药材→药膳": {herb: sorted(diets) for herb, diets in herb_diet_pairs.items()}
}
# 只保存TOP部分(全量太大)
top_herb_diet = {herb: sorted(diets) for herb, diets in herb_diet_pairs.items() if len(diets) >= 5}
top_diet_herb = {name: sorted(list(herbs)) for name, herbs in diet_to_herbs.items() if len(herbs) >= 2}
# 保存
with open(os.path.join(TOP_DIR, "索引_药膳药材双向映射.json"), "w", encoding='utf-8') as f:
json.dump({
"统计": {
"药材在药膳中使用数": len(herb_in_diet_count),
"药膳含药材数": sum(1 for h in diet_to_herbs.values() if h),
"覆盖率": round(coverage, 2)
},
"高频药材→药膳": {k: sorted(v) for k, v in sorted(herb_diet_pairs.items(), key=lambda x: -len(x))[:50]},
"药材共现TOP": herb_pair_freq.most_common(30)
}, f, ensure_ascii=False, indent=2)
# 功效交叉验证索引
with open(os.path.join(TOP_DIR, "索引_功效交叉验证.json"), "w", encoding='utf-8') as f:
json.dump({
"药膳功效大类": dict(gx_categories.most_common()),
"功效一致率": round(consistency_pct, 2),
"药食同源使用TOP": yf_usage.most_common(30),
"非药食同源使用TOP": [(h, c) for h, c in sorted(non_yf.items(), key=lambda x: -x[1])[:20]]
}, f, ensure_ascii=False, indent=2)
print(f"\n索引文件保存完毕")
print(f"\n{'='*60}")
print("分析完成!")
print("="*60)