| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- """
- 扫描 Apple Health export.xml,统计所有 Record type 和 Workout 的数量与时间范围。
- 流式解析,不吃内存。
- """
- import sys
- from collections import Counter
- from pathlib import Path
- from xml.etree.ElementTree import iterparse
- xml_path = Path(r"D:\workspace\Agi\zrd-nb666\campus_health_app\analytics\apple_health\apple_health_export\瀵煎嚭.xml")
- print(f"Parsing {xml_path.name} ({xml_path.stat().st_size/1024/1024:.1f} MB)...")
- record_types = Counter()
- workout_types = Counter()
- date_min = None
- date_max = None
- # 关心的类型样本
- samples = {}
- context = iterparse(str(xml_path), events=("end",))
- for event, elem in context:
- tag = elem.tag
- if tag == "Record":
- rtype = elem.get("type", "")
- record_types[rtype] += 1
- # 时间范围
- sd = elem.get("startDate", "")
- if sd:
- if date_min is None or sd < date_min:
- date_min = sd
- if date_max is None or sd > date_max:
- date_max = sd
- # 样本
- if rtype not in samples:
- samples[rtype] = {
- "source": elem.get("sourceName"),
- "value": elem.get("value"),
- "unit": elem.get("unit"),
- "date": sd,
- }
- elif tag == "Workout":
- wtype = elem.get("workoutActivityType", "")
- workout_types[wtype] += 1
- elem.clear()
- print(f"\n=== 时间范围 ===")
- print(f"最早: {date_min}")
- print(f"最新: {date_max}")
- print(f"\n=== Record 类型(共 {len(record_types)} 种)===")
- for rtype, cnt in record_types.most_common():
- s = samples.get(rtype, {})
- print(f"{cnt:>8} {rtype:60s} e.g. {s.get('value','')} {s.get('unit','')} via {s.get('source','')}")
- print(f"\n=== Workout 类型(共 {len(workout_types)} 种)===")
- for wtype, cnt in workout_types.most_common():
- print(f"{cnt:>8} {wtype}")
|