初始归档:健康管理资料库(大医网/药膳/体质监测/中医理论等12个资料集,7712个文件)
This commit is contained in:
commit
80ae3811cf
7712 files changed
+4628547
No files matched your search
@@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
国家学生体质健康标准(2014年修订)— 评分数据提取脚本
|
||||
教育部发布,适用于全日制小学至大学学生
|
||||
满分120分制(100基础分 + 20附加分)
|
||||
"""
|
||||
import json, os, re, sys
|
||||
from docx import Document
|
||||
|
||||
BASE = '/home/songyi/Documents/ai_agent_scraper_study/data/国家学生体质健康标准'
|
||||
DOCX = os.path.join(BASE, '01_来源数据/国家学生体质健康标准(2014年修订).docx')
|
||||
|
||||
|
||||
def parse_range(val):
|
||||
"""解析值域:'13.5~18.1', '≤13.4', '≥17.9'"""
|
||||
val = val.strip().replace(' ', '').replace('\n','')
|
||||
if re.match(r'[≥>]=?\s*([\d.]+)', val):
|
||||
m = re.match(r'[≥>]=?\s*([\d.]+)', val)
|
||||
return {"min": float(m.group(1))}
|
||||
if re.match(r'[≤<]=?\s*([\d.]+)', val):
|
||||
m = re.match(r'[≤<]=?\s*([\d.]+)', val)
|
||||
return {"max": float(m.group(1))}
|
||||
if re.match(r'([\d.]+)\s*[~-]\s*([\d.]+)', val):
|
||||
m = re.match(r'([\d.]+)\s*[~-]\s*([\d.]+)', val)
|
||||
lo, hi = float(m.group(1)), float(m.group(2))
|
||||
return {"min": min(lo, hi), "max": max(lo, hi)}
|
||||
if re.match(r'(\d+)[::·]\s*(\d+[\']?[\d.]*)', val):
|
||||
m = re.match(r'(\d+)[::·]\s*(\d+[\']?[\d.]*)', val)
|
||||
minutes = int(m.group(1))
|
||||
rest = m.group(2).replace("'", ".")
|
||||
seconds = float(rest) if '.' in rest else int(rest)
|
||||
return {"exact": minutes * 60 + seconds}
|
||||
if re.match(r'^([\d.]+)$', val):
|
||||
m = re.match(r'^([\d.]+)$', val)
|
||||
return {"exact": float(m.group(1))}
|
||||
return {"raw": val}
|
||||
|
||||
|
||||
def extract_all():
|
||||
doc = Document(DOCX)
|
||||
|
||||
result = {
|
||||
'metadata': {
|
||||
'title': '国家学生体质健康标准(2014年修订)',
|
||||
'publisher': '教育部',
|
||||
'year': 2014,
|
||||
'total_tables': len(doc.tables),
|
||||
'scoring_system': '100分基础 + 20分附加 = 120分满分',
|
||||
'rating_levels': {
|
||||
'优秀': {'min': 90.0},
|
||||
'良好': {'min': 80.0, 'max': 89.9},
|
||||
'及格': {'min': 60.0, 'max': 79.9},
|
||||
'不及格': {'max': 59.9}
|
||||
}
|
||||
},
|
||||
'weight_table': {},
|
||||
'scoring_tables': [],
|
||||
'bonus_tables': [],
|
||||
'registration_tables': []
|
||||
}
|
||||
|
||||
for i, table in enumerate(doc.tables):
|
||||
rows_data = []
|
||||
for row in table.rows:
|
||||
cells = [cell.text.strip().replace('\n', ' ') for cell in row.cells]
|
||||
rows_data.append(cells)
|
||||
|
||||
if not rows_data:
|
||||
continue
|
||||
|
||||
header = rows_data[0]
|
||||
header_str = ' '.join(str(h) for h in header).strip()
|
||||
|
||||
# 权重表(表0)
|
||||
if i == 0:
|
||||
for row in rows_data[1:]:
|
||||
if len(row) >= 3:
|
||||
obj = row[0].strip()
|
||||
indicator = row[1].strip()
|
||||
weight = row[2].strip()
|
||||
try:
|
||||
w = float(weight)
|
||||
result['weight_table'].setdefault(obj, {})[indicator] = w
|
||||
except ValueError:
|
||||
pass
|
||||
continue
|
||||
|
||||
# 登记卡表
|
||||
if '学校签章' in header_str or ('姓名' in header_str and '性别' in header_str):
|
||||
result['registration_tables'].append({
|
||||
'table_index': i, 'rows': len(rows_data), 'cols': len(header)
|
||||
})
|
||||
continue
|
||||
|
||||
# 判断加分表
|
||||
is_bonus = '加分' in header_str and '成绩' not in header_str
|
||||
|
||||
# 解析年级列
|
||||
grade_cols = []
|
||||
start_col = 1 if is_bonus else 2
|
||||
for ci, h in enumerate(header):
|
||||
h_clean = h.strip().replace('\n', ' ')
|
||||
if h_clean and ci >= start_col:
|
||||
# 跳过'单项得分'列
|
||||
if '单项' in h_clean or '得分' in h_clean:
|
||||
continue
|
||||
grade_cols.append((ci, h_clean))
|
||||
|
||||
if not grade_cols:
|
||||
continue
|
||||
|
||||
table_info = {
|
||||
'table_index': i,
|
||||
'header_sample': [h.strip() for h in header[:5]],
|
||||
'grade_names': [g[1] for g in grade_cols],
|
||||
'type': 'bonus' if is_bonus else 'standard',
|
||||
'rows_count': len(rows_data) - 1,
|
||||
'data': []
|
||||
}
|
||||
|
||||
for row in rows_data[1:]:
|
||||
if is_bonus:
|
||||
if len(row) < 2:
|
||||
continue
|
||||
bonus_str = row[0].strip()
|
||||
try:
|
||||
bonus_score = int(bonus_str) if bonus_str.lstrip('-').isdigit() else 0
|
||||
except:
|
||||
continue
|
||||
entry = {'bonus_score': bonus_score, 'grades': {}}
|
||||
for ci, gname in grade_cols:
|
||||
if ci < len(row):
|
||||
val = row[ci].strip()
|
||||
if val and val not in ['—', '-', '', '------']:
|
||||
entry['grades'][gname] = parse_range(val)
|
||||
if entry['grades']:
|
||||
table_info['data'].append(entry)
|
||||
else:
|
||||
if len(row) < 3:
|
||||
continue
|
||||
level_name = row[0].strip()
|
||||
score_str = row[1].strip()
|
||||
try:
|
||||
score_val = int(score_str) if score_str.isdigit() else 0
|
||||
except:
|
||||
continue
|
||||
entry = {'level': level_name, 'score': score_val, 'grades': {}}
|
||||
for ci, gname in grade_cols:
|
||||
if ci < len(row):
|
||||
val = row[ci].strip()
|
||||
if val and val not in ['—', '-', '', '------']:
|
||||
entry['grades'][gname] = parse_range(val)
|
||||
if entry['grades']:
|
||||
table_info['data'].append(entry)
|
||||
|
||||
if table_info['data']:
|
||||
if is_bonus:
|
||||
result['bonus_tables'].append(table_info)
|
||||
else:
|
||||
result['scoring_tables'].append(table_info)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def print_summary(data):
|
||||
m = data['metadata']
|
||||
print(f"总Word表格: {m['total_tables']}")
|
||||
print(f"标准评分表: {len(data['scoring_tables'])} 个")
|
||||
print(f"加分评分表: {len(data['bonus_tables'])} 个")
|
||||
print(f"登记卡/附表: {len(data['registration_tables'])} 个")
|
||||
|
||||
wt = data['weight_table']
|
||||
print(f"\n权重表 ({len(wt)}组):")
|
||||
for obj in sorted(wt.keys()):
|
||||
items = ', '.join(f"{k}={v}%" for k, v in sorted(wt[obj].items()))
|
||||
print(f" {obj}: {items}")
|
||||
|
||||
print(f"\n标准评分表:")
|
||||
for t in data['scoring_tables']:
|
||||
gn = t['grade_names']
|
||||
gs = ', '.join(gn[:3])
|
||||
if len(gn) > 3:
|
||||
gs += f"...({len(gn)}个年级)"
|
||||
levels = sorted(set(e['level'] for e in t['data']))
|
||||
ti = t['table_index']
|
||||
rc = len(t['data'])
|
||||
print(f" [表{ti}] {rc}行x{len(gn)}年级 等级={levels} 年级={gs}")
|
||||
|
||||
print(f"\n加分评分表:")
|
||||
for t in data['bonus_tables']:
|
||||
gn = t['grade_names']
|
||||
gs = ', '.join(gn[:3])
|
||||
if len(gn) > 3:
|
||||
gs += f"...({len(gn)}个年级)"
|
||||
ti = t['table_index']
|
||||
rc = len(t['data'])
|
||||
print(f" [表{ti}] {rc}行 年级={gs}")
|
||||
|
||||
|
||||
def output_json(data):
|
||||
path = os.path.join(BASE, '02_加工数据/评分标准结构化数据.json')
|
||||
with open(path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
size = os.path.getsize(path)
|
||||
print(f"\nJSON输出: {path} ({size/1024:.0f}KB)")
|
||||
return path
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
data = extract_all()
|
||||
print_summary(data)
|
||||
output_json(data)
|
||||
Reference in new issue
Block a user