初始归档:健康管理资料库(大医网/药膳/体质监测/中医理论等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,560 @@
#!/usr/bin/env python3
"""
中华药膳全书资料库 - 深度挖掘分析脚本
生成4个输出:
1. 药膳功效聚类.json
2. 食材药材共现网络.json
3. 药膳-体质关联.json
4. 药膳深度挖掘报告.md
"""
import json
import re
from collections import defaultdict, Counter
BASE = "/home/songyi/Documents/ai_agent_scraper_study/data/中华药膳全书学做药膳不生病"
# ─── 加载数据 ───────────────────────────────────────
def load_json(path):
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
调理药膳 = load_json(f"{BASE}/01_来源数据/调理药膳.json")
配方库 = load_json(f"{BASE}/01_来源数据/药膳配方库_recipes.json")
中药表 = load_json(f"{BASE}/01_来源数据/药膳常用中药功能表.json")
食物表 = load_json(f"{BASE}/01_来源数据/药膳常用食物功能表.json")
print(f"调理药膳: {len(调理药膳)}条")
print(f"配方库: {len(配方库)}条")
print(f"中药表: {len(中药表)}条")
print(f"食物表: {len(食物表)}条")
# ─── 提取名称列表(用于最长前缀匹配) ─────────────
中药名列表 = sorted([h['名称'] for h in 中药表 if h.get('名称')], key=len, reverse=True)
食物名列表 = sorted([f['名称'] for f in 食物表 if f.get('名称')], key=len, reverse=True)
# 统一别名处理:一些常见别名/变体
别名映射 = {
'枸杞': '枸杞子',
'杞子': '枸杞子',
'意薏苡仁': '薏苡仁',
'薏苡仁': '薏苡仁',
'薏仁': '薏苡仁',
'白萝ト': '白萝卜',
'胡萝ト': '胡萝卜',
'芝庥': '芝麻',
'川穹': '川芎',
'有郁李仁': '郁李仁',
'土茯': '土茯苓',
'枣': '大枣',
'红枣': '大枣',
'元肉': '龙眼肉',
'桂圆': '龙眼肉',
'田七': '三七',
'淮山': '山药',
'淮山药': '山药',
'云苓': '茯苓',
'川仲': '杜仲',
}
# 扩充别名
中药别名扩充 = {}
for h in 中药表:
name = h.get('名称','')
if name:
中药别名扩充[name] = name
aliases = h.get('别名','')
if aliases:
for a in re.split(r'[、,,;;。.\s]', aliases):
a = a.strip()
if a and len(a) >= 2:
中药别名扩充[a] = name
食物别名扩充 = {}
for f in 食物表:
name = f.get('名称','')
if name:
食物别名扩充[name] = name
aliases = f.get('别名','')
if aliases:
for a in re.split(r'[、,,;;。.\s]', aliases):
a = a.strip()
if a and len(a) >= 2:
食物别名扩充[a] = name
# 合并别名
中药别名扩充.update(别名映射)
食物别名扩充.update(别名映射)
# 构建最长前缀匹配函数
def 最长前缀匹配(text, name_list, alias_map):
"""在text中查找name_list中的名称(最长前缀匹配)"""
found = set()
if not text:
return found
for name in name_list:
if name in text:
found.add(name)
continue
# 尝试别名
for alias, standard in alias_map.items():
if standard == name and alias in text:
found.add(name)
break
return found
def 匹配中药(text):
return 最长前缀匹配(text or '', 中药名列表, 中药别名扩充)
def 匹配食物(text):
return 最长前缀匹配(text or '', 食物名列表, 食物别名扩充)
# ═══════════════════════════════════════════════════════
# 输出1:药膳功效聚类分析
# ═══════════════════════════════════════════════════════
print("\n=== 输出1:药膳功效聚类分析 ===")
# 功效关键词体系(多级)
功效关键词 = [
'补气', '益气', '补中益气',
'养血', '补血', '活血', '化瘀',
'滋阴', '养阴', '生津',
'健脾', '补脾', '温脾',
'补肾', '益肾', '温肾', '壮阳',
'养肝', '疏肝', '清肝', '平肝',
'润肺', '清肺', '补肺', '止咳',
'安神', '养心', '宁心',
'清热', '解毒', '降火', '泻火',
'祛湿', '利湿', '化湿', '渗湿',
'化痰', '祛痰',
'消食', '开胃', '导滞',
'通便', '润肠',
'祛风', '散寒', '温中',
'明目', '乌发',
'利水', '消肿',
'降压', '降脂', '降糖',
'强筋骨', '壮骨',
'抗衰老', '延年',
'固表', '固涩',
'理气', '行气',
'排毒', '养颜',
]
def 提取功效(text):
"""从文本中提取功效关键词"""
found = set()
if not text:
return found
for kw in 功效关键词:
if kw in text:
found.add(kw)
return found
# 合并所有药膳数据
所有药膳 = []
for item in 调理药膳:
所有药膳.append({
'name': item.get('名称',''),
'source': '调理药膳',
'symptom': item.get('症状',''),
'material': item.get('材料准备',''),
'process': item.get('制作过程',''),
'effect': item.get('功能效用',''),
})
for item in 配方库:
所有药膳.append({
'name': item.get('name',''),
'source': '配方库',
'category': item.get('category',''),
'material': item.get('材料准备',''),
'process': item.get('制作过程',''),
'effect': item.get('功能效用',''),
})
# 统计功效频率
功效频率 = Counter()
功效药膳集 = defaultdict(list) # 功效 -> [(name, source, effect)]
for item in 所有药膳:
effects = 提取功效(item['effect'])
effects |= 提取功效(item['material']) # 材料也可能有功效提示
for kw in effects:
功效频率[kw] += 1
功效药膳集[kw].append({
'name': item['name'],
'source': item['source'],
'effect': item['effect'][:100] + '...' if len(item.get('effect','')) > 100 else item.get('effect','')
})
print(f"提取到 {len(功效频率)} 种功效关键词")
for kw, cnt in 功效频率.most_common(20):
print(f" {kw}: {cnt}")
# 共现分析:哪些功效常同时出现
功效共现 = defaultdict(lambda: defaultdict(int))
功效共现矩阵 = []
for item in 所有药膳:
effects = list(提取功效(item['effect']) | 提取功效(item['material']))
for i in range(len(effects)):
for j in range(i+1, len(effects)):
a, b = sorted([effects[i], effects[j]])
功效共现[a][b] += 1
# 构建共现列表
共现列表 = []
for a in 功效共现:
for b in 功效共现[a]:
cnt = 功效共现[a][b]
if cnt >= 2: # 过滤低频
共现列表.append([a, b, cnt])
共现列表.sort(key=lambda x: x[2], reverse=True)
print(f"功效共现对(>=2次): {len(共现列表)}")
# 每种功效的TOP10药膳
功效TOP10 = {}
for kw in 功效关键词:
items = 功效药膳集.get(kw, [])
# 去重
seen = set()
unique = []
for it in items:
key = it['name'] + it['source']
if key not in seen:
seen.add(key)
unique.append(it)
unique = unique[:10]
if unique:
功效TOP10[kw] = unique
# 组装输出1
输出1 = {
"功效频率统计": {kw: cnt for kw, cnt in 功效频率.most_common()},
"功效共现分析": 共现列表,
"功效关联药膳TOP10": {kw: items for kw, items in 功效TOP10.items()},
"统计": {
"总功效种类数": len(功效频率),
"总药膳数": len(所有药膳),
"高频率功效(>=20)": [{"功效": kw, "频次": cnt} for kw, cnt in 功效频率.most_common() if cnt >= 20]
}
}
with open(f"{BASE}/02_加工数据/药膳功效聚类.json", 'w', encoding='utf-8') as f:
json.dump(输出1, f, ensure_ascii=False, indent=2)
print("✓ 药膳功效聚类.json 写入完成")
# ═══════════════════════════════════════════════════════
# 输出2:食材-药材共现网络
# ═══════════════════════════════════════════════════════
print("\n=== 输出2:食材-药材共现网络 ===")
# 对所有药膳的材料准备字段做匹配
单品频率 = Counter()
共现对 = defaultdict(int)
for item in 所有药膳:
material = item.get('material', '')
herbs = 匹配中药(material)
foods = 匹配食物(material)
# 单品频率
for h in herbs:
单品频率[h] += 1
for f in foods:
单品频率[f] += 1
# 共现对:药材-药材、药材-食物
all_ingredients = list(herbs) + list(foods)
for i in range(len(all_ingredients)):
for j in range(i+1, len(all_ingredients)):
a, b = sorted([all_ingredients[i], all_ingredients[j]])
共现对[(a, b)] += 1
# 转换为输出格式
共现对列表 = [[a, b, cnt] for (a, b), cnt in 共现对.items()]
共现对列表.sort(key=lambda x: x[2], reverse=True)
# 过滤低频
共现对列表_high = [p for p in 共现对列表 if p[2] >= 3]
输出2 = {
"共现对": 共现对列表_high,
"单品频率": {k: v for k, v in 单品频率.most_common()},
"统计": {
"总共现对数": len(共现对),
"高频共现对(>=3次)": len(共现对列表_high),
"总单品数": len(单品频率),
"高频单品(>=10次)": [{"名称": k, "频次": v} for k, v in 单品频率.most_common() if v >= 10]
}
}
with open(f"{BASE}/02_加工数据/食材药材共现网络.json", 'w', encoding='utf-8') as f:
json.dump(输出2, f, ensure_ascii=False, indent=2)
print("✓ 食材药材共现网络.json 写入完成")
# ═══════════════════════════════════════════════════════
# 输出3:药膳-体质关联增强
# ═══════════════════════════════════════════════════════
print("\n=== 输出3:药膳-体质关联增强 ===")
九种体质关键字 = {
"气虚质": ['补气','益气','黄芪','党参','白术','山药','大枣','气虚','乏力'],
"阳虚质": ['温阳','散寒','生姜','肉桂','羊肉','韭菜','干姜','阳虚','畏寒'],
"阴虚质": ['滋阴','润燥','百合','麦冬','沙参','玉竹','枸杞','阴虚','口干'],
"痰湿质": ['化痰','祛湿','陈皮','茯苓','薏米','赤小豆','荷叶','痰湿','肥胖'],
"湿热质": ['清热','利湿','绿豆','冬瓜','苦瓜','薏苡仁','湿热','口苦'],
"血瘀质": ['活血','化瘀','山楂','红花','当归','川芎','玫瑰','血瘀','刺痛'],
"气郁质": ['疏肝','理气','柴胡','香附','薄荷','玫瑰花','气郁','胸闷'],
"特禀质": ['固表','祛风','黄芪','白术','防风','过敏','鼻塞','哮喘'],
"平和质": ['平和','平衡','均衡','保健','养生','五谷杂粮'],
}
# 一些同义词/别名映射用于体质匹配
体质别名 = {
'薏米': '薏苡仁',
'杞子': '枸杞子',
'红枣': '大枣',
'桂圆': '龙眼肉',
}
def 计算体质得分(item, keywords):
"""计算一个药膳与某种体质的匹配得分"""
score = 0
reasons = []
fields = {
'name': item.get('name',''),
'material': item.get('material',''),
'effect': item.get('effect',''),
'symptom': item.get('symptom',''),
}
text_all = ' '.join(fields.values())
for kw in keywords:
# 直接匹配
if kw in text_all:
score += 2
reasons.append(kw)
continue
# 尝试别名
alias = 体质别名.get(kw)
if alias and alias in text_all:
score += 2
reasons.append(kw)
continue
# 模糊匹配(部分匹配,针对复合词)
# 如果关键字是2个字,放宽匹配
if len(kw) == 2:
if kw in text_all.replace(' ','').replace(',','').replace('、',''):
score += 1
reasons.append(kw)
return score, reasons
体质结果 = {}
for 体质, keywords in 九种体质关键字.items():
药膳得分列表 = []
for item in 所有药膳:
score, reasons = 计算体质得分(item, keywords)
if score >= 2 and len(reasons) >= 1:
药膳得分列表.append({
'药膳名': item['name'],
'来源': item['source'],
'得分': score,
'匹配理由': reasons[:6] # 最多6个
})
# 按得分降序,取TOP50
药膳得分列表.sort(key=lambda x: x['得分'], reverse=True)
体质结果[体质] = 药膳得分列表[:50]
print(f" {体质}: {len(药膳得分列表)}条匹配")
输出3 = 体质结果
with open(f"{BASE}/02_加工数据/药膳-体质关联.json", 'w', encoding='utf-8') as f:
json.dump(输出3, f, ensure_ascii=False, indent=2)
print("✓ 药膳-体质关联.json 写入完成")
# ═══════════════════════════════════════════════════════
# 输出4:深度挖掘报告(Markdown)
# ═══════════════════════════════════════════════════════
print("\n=== 输出4:深度挖掘报告 ===")
# 分类类别统计(从配方库)
分类统计 = Counter()
for item in 配方库:
cat = item.get('category', '未分类')
分类统计[cat] += 1
# 体质TOP10
体质TOP10输出 = {}
for 体质 in 九种体质关键字:
items = 输出3.get(体质, [])[:10]
体质TOP10输出[体质] = items
# 功效TOP20
功效TOP20 = 功效频率.most_common(20)
# 食材-药材高频共现TOP30
共现TOP30 = 共现对列表_high[:30]
md = f"""# 中华药膳全书 - 深度挖掘分析报告
> 生成日期: 自动分析
> 数据来源: 中华药膳全书学做药膳不生病资料库
---
## 一、数据概览
| 数据源 | 记录数 |
|--------|--------|
| 调理药膳 | {len(调理药膳)} 条 |
| 药膳配方库 | {len(配方库)} 条 |
| 中药功能表 | {len(中药表)} 种 |
| 食物功能表 | {len(食物表)} 种 |
| 合并药膳总数 | {len(所有药膳)} 条 |
---
## 二、药膳分类类别统计
| 分类 | 数量 |
|------|------|
"""
for cat, cnt in 分类统计.most_common():
md += f"| {cat} | {cnt} |\n"
md += f"""
---
## 三、药膳功效聚类 TOP20
| 排名 | 功效关键词 | 出现频次 |
|------|-----------|---------|
"""
for i, (kw, cnt) in enumerate(功效TOP20, 1):
md += f"| {i} | {kw} | {cnt} |\n"
md += f"""
### 功效共现分析(高频共现对 TOP20)
功效共现分析揭示哪些功效常在同一道药膳中同时出现:
| 排名 | 功效A | 功效B | 共现次数 |
|------|-------|-------|---------|
"""
for i, (a, b, cnt) in enumerate(共现列表[:20], 1):
md += f"| {i} | {a} | {b} | {cnt} |\n"
md += """
---
## 四、食材-药材高频共现 TOP30
| 排名 | 食材/药材1 | 食材/药材2 | 共现次数 |
|------|-----------|-----------|---------|
"""
for i, (a, b, cnt) in enumerate(共现TOP30, 1):
md += f"| {i} | {a} | {b} | {cnt} |\n"
md += """
### 高频单品 TOP20
| 排名 | 食材/药材 | 使用频次 |
|------|-----------|---------|
"""
for i, (k, v) in enumerate(单品频率.most_common(20), 1):
md += f"| {i} | {k} | {v} |\n"
md += """
---
## 五、各类体质推荐药膳 TOP10
"""
for 体质, items in 体质TOP10输出.items():
md += f"""### {体质}
| 序号 | 药膳名称 | 来源 | 匹配得分 | 匹配理由 |
|------|----------|------|---------|---------|
"""
for i, it in enumerate(items, 1):
reasons = '、'.join(it['匹配理由'][:4])
md += f"| {i} | {it['药膳名']} | {it['来源']} | {it['得分']} | {reasons} |\n"
md += "\n"
md += """
---
## 六、分析结论
### 6.1 功效分布特征
"""
# 找最高频的3个功效
top3_eff = 功效频率.most_common(3)
if len(top3_eff) >= 1:
md += f"- 最高频功效关键词为「{top3_eff[0][0]}」({top3_eff[0][1]}次),其次为「{top3_eff[1][0]}」({top3_eff[1][1]}次)、「{top3_eff[2][0]}」({top3_eff[2][1]}次)\n"
md += f"- 共提取到 {len(功效频率)} 种不同功效关键词,{len(共现列表)} 组有效共现对\n"
# 找最高频共现
if 共现列表:
top_co = 共现列表[0]
md += f"- 功效共现组合中最引人注目的是「{top_co[0]}+{top_co[1]}」({top_co[2]}次),反映了药膳配伍中的经典搭配\n"
md += """
### 6.2 食材-药材配伍规律
"""
if 共现对列表_high:
top_pair = 共现对列表_high[0]
md += f"- 最高频食材-药材搭配为「{top_pair[0]}+{top_pair[1]}」({top_pair[2]}次)\n"
if len(共现对列表_high) >= 2:
top_pair2 = 共现对列表_high[1]
md += f"- 其次为「{top_pair2[0]}+{top_pair2[1]}」({top_pair2[2]}次)\n"
if len(单品频率) >= 1:
top_single = 单品频率.most_common(1)[0]
md += f"- 使用频率最高的单品是「{top_single[0]}」({top_single[1]}次)\n"
md += f"- 共发现 {len(共现对)} 组食材-药材共现关系,{len(单品频率)} 种单品\n"
md += """
### 6.3 体质匹配覆盖
"""
for 体质 in 九种体质关键字:
cnt = len(体质结果.get(体质, []))
md += f"- {体质}:匹配到 {cnt} 道药膳\n"
md += """
---
*报告完毕*
"""
with open(f"{BASE}/04_分析报告/药膳深度挖掘报告.md", 'w', encoding='utf-8') as f:
f.write(md)
print("✓ 药膳深度挖掘报告.md 写入完成")
print("\n🎉 所有分析输出已完成!")