TFT 阵容顾问(AI Agent)第一章之数据下载爬虫篇
前言
一款基于Python和大语言模型的云顶之弈智能分析工具,提供三种阵容输入方式:截图识别、文本/JSON导入以及可视化棋盘。该工具采用RAG检索增强生成技术,结合KR服高端局对战数据,为用户提供专业的阵容评价和进阶发展建议。
作为一名《云顶之弈》(Teamfight Tactics, TFT)的普通玩家,同时也是计算机专业的学生,我研究了拳头游戏(Riot Games)对外开放的数据接口,并写了一个自动抓取赛季数据的 Python 脚本。
这篇博客将完整介绍这个小项目的实现思路,作为该项目中下载的第一步,并穿插一些我在学习过程中收获的技术点与思考。
工具最终效果:运行一条命令,就能在当前文件夹生成 6 个 JSON 文件,包含当前赛季全部英雄、羁绊、装备的结构化数据。
数据从哪里来?—— CommunityDragon 与 Data Dragon
在动手之前,先要解决数据源的问题。官方提供给开发者的主要有两个渠道:
| 数据源 | 特点 | 时效性 | 使用场景 |
|---|---|---|---|
| Data Dragon (DDragon) | Riot 官方 CDN,稳定可靠 | 通常滞后于正式服几天 | 基础数据、历史版本 |
| CommunityDragon (CDragon) | 社区维护,直接从游戏客户端解包 | 接近实时,甚至包含 PBE 内容 | 最新赛季、测试服数据 |
我们的脚本会优先尝试 CDragon,因为它的数据更新最快,且字段更加丰富;如果 CDragon 请求失败,则自动回退到 DDragon,保证工具始终能用。
代码整体结构
┌─────────────────┐
│ 命令行参数解析 │
└────────┬────────┘
▼
┌─────────────────┐
│ 尝试 CDragon │──成功──► 解析数据
└────────┬────────┘
│失败
▼
┌─────────────────┐
│ 尝试 DDragon │──成功──► 解析数据
└────────┬────────┘
│失败
▼
┌─────────────────┐
│ 报错退出 │
└─────────────────┘
数据解析完成后,统一保存为以下文件(全部使用英文 ID):
tft_champion_db.json —— 英雄详情(费用、羁绊列表、基础属性)
tft_trait_db.json —— 羁绊信息(激活阈值、效果描述)
tft_item_db.json —— 装备信息(名称、合成配方)
tft_champion_trait_map.json —— 英雄→羁绊映射表
tft_trait_champion_dict.json —— 羁绊→英雄聚合表
tft_meta.json —— 版本元数据(来源、版本号、生成时间)
关键函数
1. 获取 DDragon 最新版本号
def get_ddragon_version() -> str:
r = requests.get("https://ddragon.leagueoflegends.com/api/versions.json", timeout=15)
return r.json()[0]
DDragon 提供了一个版本列表 API,返回形如 ["15.12.1", "15.11.1", ...] 的数组,第一个元素即最新版本。
这个版本号将作为后续请求 DDragon 具体数据的路径参数。
小思考:为什么这里要加 timeout=15?如果不设置超时,万一网络波动,程序就会一直卡住,用户体验极差。编写任何网络请求代码时,超时设置是必须的。(此案例不来源于网络素材)
2. 去除 API 名称中的冗余前缀 —— _strip
def _strip(s: str, n: int) -> str:
s = re.sub(rf"^TFT{n}_", "", s)
s = re.sub(r"^TFTSet\d+_", "", s)
s = re.sub(r"^Set\d+_", "", s)
s = re.sub(r"^TFT_", "", s)
return s
无论是 DDragon 还是 CDragon,英雄或羁绊的 API 名称通常包含类似 TFT16_ 或 TFTSet16_ 的前缀。
为了便于跨赛季数据对比和后续查询,我们需要将这些名称转换为简洁格式,例如将 TFT16_Aatrox 转换为 Aatrox。
为此,我们使用正则表达式依次匹配并删除四种常见前缀格式,其中 rf 前缀支持动态插入赛季编号。
学习点:正则表达式是处理字符串的利器,re.sub(pattern, replacement, string) 会将匹配到的部分替换为空字符串,达到“删除”的效果。
3. 从 CommunityDragon 抓取数据
def fetch_cdragon(set_number: int) -> Optional[Dict]:
patches = ["latest", "16.12", "16.10", "16.8", "16.6", "16.5", "16.3", "16.1", "pbe"]
for patch in patches:
url = f"https://raw.communitydragon.org/{patch}/cdragon/tft/en_us.json"
# ... 发起请求 ...
data = r.json()
sets = data.get("sets", {})
sd = sets.get(str(set_number)) or sets.get(f"set{set_number}") or sets.get(set_number)
CDragon 的文件按 patch 版本组织(例如 16.12、pbe)。由于不知道目标赛季存在于哪个 patch 下,我们按顺序尝试一个预设列表。
拿到 JSON 后,需要找到当前赛季的数据集。CDragon 的顶层对象通常有一个 sets 字段,键可能是 "16"、"set16" 或数字 16,因此用了三种方式尝试取值。
如果能取到非空数据(包含 champions 和 traits),就返回完整数据块,否则继续尝试下一个 patch。
技术要点:
请求之间加入 time.sleep(0.4),避免因频率过高被服务器短暂封禁——这是爬虫最基本的礼仪。
使用 Optional[Dict] 类型标注,清晰地告诉调用者:可能返回 None。
4. DDragon 备用数据源
def fetch_ddragon(set_number: int, version: str) -> Optional[Dict]:
base = f"https://ddragon.leagueoflegends.com/cdn/{version}/data/en_US"
prefix = f"TFT{set_number}_"
for ep, key in [("tft-champion.json", "champions"), ...]:
r = requests.get(f"{base}/{ep}")
raw = r.json().get("data", {})
filtered = {k: v for k, v in raw.items() if k.startswith(prefix)}
result[key] = filtered
DDragon 的数据按文件类型拆分(英雄、羁绊、装备分开)。
每个文件返回一个以 API 名称为键的大字典,我们需要筛选出以 TFT{赛季号}_ 开头的项,才是当前赛季的数据。
虽然 DDragon 的数据量较少(不包含基础装备等),但足以作为后备方案。
5. 数据解析
解析函数 parse_cdragon(raw) 是整个脚本的大脑。
我将重点讲解其中最精巧的设计:羁绊反查表的建立。
背景问题:
CDragon 英雄对象的 traits 字段是一个字符串列表,例如 ["Bruiser", "Quickstriker"]。
但这里的 "Quickstriker" 是显示名称(display name),而羁绊对象的 apiName 经过 strip 后得到的是 "Rapidfire"。
如果直接用显示名称去匹配羁绊的 short_id,会直接失败。
解决方案:建立 name_to_short 反查表
name_to_short: Dict[str, str] = {}
for t in raw.get("traits", []):
api = t.get("apiName", "")
short = _strip(api, n)
name = t.get("name", short)
# 双向注册
name_to_short[short] = short
name_to_short[name] = short
这样一来,无论英雄列表里是 short_id 还是显示名称,都能统一转换成标准的 short_id。
for t in raw_traits:
t_stripped = _strip(t, n)
traits.append(name_to_short.get(t_stripped, name_to_short.get(t, t_stripped)))
被脏数据气笑过
6. 保存聚合数据
解析完成后,我们不仅保存原始信息,还额外生成了两个聚合文件:
tft_champion_trait_map.json:{"TFT16_Aatrox": ["Bruiser", "Dragon"]}
tft_trait_champion_dict.json:以羁绊为键,汇总所有拥有该羁绊的英雄列表及激活阈值。
这两个文件可以极大地方便下游应用——比如查询“哪些英雄拥有 Bruiser 羁绊”,直接读取第二个文件即可,无需遍历整个英雄数据库。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)