#!/usr/bin/env python3 # -*- coding: utf-8 -*- """parse-cosyvoice-dom.py — 解析阿里云 CosyVoice 音色页面 DOM,输出 JSON + 摘要""" import re import json import sys from collections import defaultdict PATH = r"C:/Users/caoyg/AppData/Local/Temp/cosyvoice.html" text = open(PATH, encoding='utf-8').read() # 切分 4 个模型段 SECTIONS = [ ('cosyvoice-v3-flash', r'cosyvoice-v3-flash音色列表(.*?)cosyvoice-v3-plus音色列表'), ('cosyvoice-v3-plus', r'cosyvoice-v3-plus音色列表(.*?)(?=下一篇|cosyvoice-v2音色列表)'), ('cosyvoice-v2', r'cosyvoice-v2音色列表(.*?)cosyvoice-v1音色列表'), ('cosyvoice-v1', r'cosyvoice-v1音色列表(.*?)(?=上一篇|下一篇|\Z)'), ] all_models = {} for model, pat in SECTIONS: m = re.search(pat, text, re.DOTALL) if not m: continue section = m.group(1) voices = [] positions = [mm.start() for mm in re.finditer(r'名称[::]\s*.+?\n', section)] positions.append(len(section)) for i in range(len(positions) - 1): chunk = section[positions[i]:positions[i+1]] voice = {} n = re.search(r'^名称[::]\s*(.+?)\s*$', chunk, re.MULTILINE) if n: voice['name'] = n.group(1).strip() v = re.search(r'voice参数[::]\s*(\w+)', chunk) if v: voice['voice_id'] = v.group(1) t = re.search(r'特质[::]\s*(.+?)\n', chunk) if t: voice['desc'] = t.group(1).strip()[:80] a = re.search(r'年龄[::]\s*(.+?)\n', chunk) if a: voice['age'] = a.group(1).strip() l = re.search(r'语言[::]\s*(.+?)\n', chunk) if l: voice['lang'] = l.group(1).strip()[:60] voice['instruct'] = '支持' if 'Instruct:支持' in chunk else '不支持' if 'Instruct:不支持' in chunk else '?' # scene/地区 s = re.search(r'适用场景[::]\s*(.+?)\n', chunk) if s: voice['scene'] = s.group(1).strip()[:40] if voice.get('name'): voices.append(voice) all_models[model] = voices # 输出 JSON with open(r"C:/Users/caoyg/AppData/Local/Temp/cosyvoice-voices.json", "w", encoding="utf-8") as f: json.dump(all_models, f, ensure_ascii=False, indent=2) # 输出摘要 sys.stdout.reconfigure(encoding='utf-8') for model, voices in all_models.items(): print(f"\n=== {model}: {len(voices)} 个音色 ===") lang_count = defaultdict(int) for v in voices: lang = v.get('lang', '?') # 简化为第一个语种 first = lang.split('、')[0].split('(')[0] lang_count[first] += 1 print(f" 语种分布:") for lang, cnt in sorted(lang_count.items(), key=lambda x: -x[1]): print(f" {lang}: {cnt}")