十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python实战:调用PokeAPI分析传说宝可梦种族值可视化

Python实战:调用PokeAPI分析传说宝可梦种族值可视化 最近宝可梦动画新篇章的热度又上来了烈空坐、基格尔德这类传说宝可梦到底谁更强、种族值差异在哪里、闪光的稀有形态长什么样成了很多训练家茶余饭后讨论的话题。抛开对战层面的争论不谈作为开发者其实可以把“宝可梦数据”当做一个非常合适的练手项目用 Python 调用公开接口拉取图鉴信息清洗之后做可视化对比。这个过程既不涉及复杂的业务逻辑又能把网络请求、JSON 解析、DataFrame 处理、图表绘制这些高频技能完整过一遍。本文就围绕这个话题从零实现一套传说宝可梦数据采集与分析小工具。无论你是刚学 Python 不久的初学者还是已经写过不少脚本、想找一个干净数据源练习数据分析的开发者这篇文章都值得收藏。我们会先了解数据从哪来再设计代码架构最后输出可视化图表顺带把常见报错和工程习惯一起讲清楚。1. 背景与核心概念1.1 为什么要用 Python 分析宝可梦数据宝可梦系列发展这么多年积累了非常庞大的游戏数据全国图鉴编号、属性组合、种族值、特性、招式、进化链、闪光形态、隐藏特性等等。这些数据天然就是结构化的非常适合用来练习接口调用和数据分析。之前很多人学爬虫时习惯拿电影网站、电商页面来练手但这类网站往往有比较复杂的前端渲染和反爬机制新手很容易卡在第一步。而宝可梦数据接口是公开的、免认证的、返回标准 JSON简直就是为练手设计的。用 Python 把它拉下来你可以很自然地掌握 requests 请求、JSON 字典操作、pandas 清洗、matplotlib 可视化还能在项目里看到真实的数据规模。1.2 核心数据源PokeAPI 是什么本文使用的数据源是 PokeAPI一个面向宝可梦系列游戏的开放 REST API。它把全国图鉴、宝可梦详情、属性、特性、招式、进化链等数据整理成标准接口开发者只需要发送 HTTP 请求就能拿到 JSON 格式的响应。我们最常用的接口格式是https://pokeapi.co/api/v2/pokemon/{id_or_name}其中{id_or_name}可以替换成数字编号比如1也可以替换成英文名比如rayquaza。使用名称的优点是代码可读性强不需要额外记忆图鉴编号。这里要提醒一点接口的字段结构在不同时期可能会有调整。本文示例代码基于目前常用的字段名编写你在自己运行时如果发现字段缺失可以先打印原始 JSON 看一下结构再针对性修改。1.3 几个容易混淆的概念种族值宝可梦的六项基础能力值包括 HP、攻击、防御、特攻、特防、速度。它是判断一只宝可梦强弱的核心指标。属性宝可梦的属性组合例如烈空坐是龙/飞行基格尔德是龙/地面。属性会影响招式克制关系。闪光形态英文叫 Shiny也就是颜色与普通形态不同的稀有变体。PokeAPI 的sprites字段里会区分普通图片和闪光图片。本文实战部分会重点围绕种族值、属性和闪光图片展开。2. 环境准备与版本说明2.1 基础环境本文示例基于 Python 3。具体小版本号的影响不大建议使用 3.8 及以上版本我在示例中使用的语法都兼容这个范围。需要安装的第三方库如下库名作用requests发送 HTTP 请求获取接口数据pandas数据清洗与结构化处理matplotlib绘图与可视化seaborn可选用于增强图表样式如果你的环境还没有这些库可以在命令行执行pip install requests pandas matplotlib seaborn如果你习惯使用虚拟环境可以先创建并激活虚拟环境再安装python -m venv venvWindows 下激活方式venv\Scripts\activatemacOS / Linux 下激活方式source venv/bin/activate2.2 项目结构为了保证代码清晰我们按下面的结构组织项目pokemon-analysis/ ├── main.py ├── pokemon_api.py └── output/pokemon_api.py封装接口请求和数据解析函数。main.py程序入口负责调用函数、生成图表。output/存放生成的图片文件。示例项目不大文件拆分只是为了让你养成好的代码习惯。后面如果功能变多这个结构可以平滑扩展。3. 核心语法与接口解析3.1 requests 基础用法我们用requests.get()请求接口用timeout参数控制超时时间import requests url https://pokeapi.co/api/v2/pokemon/rayquaza resp requests.get(url, timeout10) print(resp.status_code)如果返回200说明请求成功。然后调用resp.json()可以得到字典类型的数据data resp.json() print(data[name]) print(data[id]) print(data[types])这里要注意resp.json()只适合 JSON 格式的响应。如果接口返回的不是 JSON会抛出requests.exceptions.JSONDecodeError这种情况一般需要检查 URL 是否正确。3.2 掌握返回的 JSON 结构以烈空坐为例我们关心几个字段{ id: 384, name: rayquaza, types: [ { slot: 1, type: { name: dragon } }, { slot: 2, type: { name: flying } } ], stats: [ { base_stat: 105, stat: { name: hp } } ], sprites: { front_default: https://..., front_shiny: https://... } }这段结构里面有几个细节值得注意types是列表因为宝可梦可以拥有两个属性。我们需要遍历列表取出每个type.name。stats也是列表里面每一项包含base_stat和stat.name。sprites是字典front_default是普通正面图front_shiny是闪光正面图。理解嵌套结构之后接下来就可以封装成函数了。3.3 封装数据解析函数我们不希望主程序里堆满一层层的字典下标所以把解析逻辑封装起来。示例写法如下def parse_pokemon(data): name data[name] types [ item[type][name] for item in data[types] ] stats {} for item in data[stats]: stat_name item[stat][name] stats[stat_name] item[base_stat] sprites { default: data[sprites].get(front_default), shiny: data[sprites].get(front_shiny), } return { name: name, types: types, stats: stats, sprites: sprites, }这个函数把原始 JSON 转换成一个更友好的结构后续 pandas 和 matplotlib 使用起来都会方便很多。4. 完整实战传说宝可梦数据采集与可视化4.1 创建项目结构与文件先在项目目录下创建pokemon_api.py文件。这个文件负责所有与接口相关的逻辑# 文件路径pokemon-analysis/pokemon_api.py import requests import time BASE_URL https://pokeapi.co/api/v2 def fetch_pokemon(name): url f{BASE_URL}/pokemon/{name.lower()} resp requests.get(url, timeout10) resp.raise_for_status() return resp.json() def parse_pokemon(data): name data[name] types [ item[type][name] for item in data[types] ] stats {} for item in data[stats]: stat_name item[stat][name] stats[stat_name] item[base_stat] sprites { default: data[sprites].get(front_default), shiny: data[sprites].get(front_shiny), } return { name: name, types: types, stats: stats, sprites: sprites, } def collect_pokemon(names): result [] for name in names: print(f正在获取 {name} 的数据...) try: data fetch_pokemon(name) result.append(parse_pokemon(data)) except requests.RequestException as e: print(f获取 {name} 失败: {e}) time.sleep(0.5) return result这里面有几个值得学习的点resp.raise_for_status()会在 HTTP 状态码为 4xx / 5xx 时抛出异常方便及时发现问题。time.sleep(0.5)是为了控制请求频率避免短时间大量请求给服务器带来压力。try/except捕获网络异常保证单个宝可梦请求失败不会导致整个脚本中断。4.2 安装依赖在命令行执行pip install requests pandas matplotlib seaborn如果你的环境已经安装过这些库可以忽略这一步。4.3 编写数据清洗与画图逻辑接下来创建主程序main.py。我们选择一批传说宝可梦作为分析对象包括烈空坐、基格尔德、帕路奇亚、帝牙卢卡、骑拉帝纳等。这里可以自己按喜好扩充列表。# 文件路径pokemon-analysis/main.py import pandas as pd import matplotlib.pyplot as plt from pokemon_api import collect_pokemon def build_dataframe(pokemon_list): rows [] for p in pokemon_list: stats p[stats] row { name: p[name], types: /.join(p[types]), hp: stats.get(hp, 0), attack: stats.get(attack, 0), defense: stats.get(defense, 0), special-attack: stats.get(special-attack, 0), special-defense: stats.get(special-defense, 0), speed: stats.get(speed, 0), } rows.append(row) return pd.DataFrame(rows) def plot_stats_bar(df): df_melted df.melt( id_vars[name], value_vars[hp, attack, defense, special-attack, special-defense, speed], var_namestat, value_namevalue, ) plt.figure(figsize(12, 6)) for name in df[name]: subset df_melted[df_melted[name] name] plt.plot(subset[stat], subset[value], markero, labelname) plt.title(传说宝可梦种族值对比) plt.xlabel(能力项) plt.ylabel(种族值) plt.legend() plt.grid(True, linestyle--, alpha0.6) plt.tight_layout() plt.savefig(output/stats_bar.png, dpi150) plt.show()这段代码的思路是把解析好的列表转成 DataFrame。用melt把宽的 DataFrame 转成长格式方便 matplotlib 按宝可梦名称分组画折线图。保存图片到output目录。4.4 运行主程序在main.py中补充入口逻辑# 文件路径pokemon-analysis/main.py import os if __name__ __main__: os.makedirs(output, exist_okTrue) pokemon_names [ rayquaza, zygarde, palkia, dialga, giratina, kyogre, groudon, ] raw_data collect_pokemon(pokemon_names) df build_dataframe(raw_data) print(df) plot_stats_bar(df)然后在项目根目录执行python main.py预期输出会先打印获取日志正在获取 rayquaza 的数据... 正在获取 zygarde 的数据... 正在获取 palkia 的数据... 正在获取 dialga 的数据... 正在获取 giratina 的数据... 正在获取 kyogre 的数据... 正在获取 groudon 的数据...随后打印 DataFrame 表格并弹出种族值对比折线图。4.5 闪光形态图片下载与对比除了数据对比我们也可以把闪光图片下载到本地。这里用一个小函数实现# 继续在 main.py 中添加 import requests def download_image(url, save_path): if not url: print(图片地址为空跳过下载) return resp requests.get(url, timeout10) resp.raise_for_status() with open(save_path, wb) as f: f.write(resp.content) print(f已保存: {save_path}) def download_shiny_images(pokemon_list): for p in pokemon_list: shiny_url p[sprites].get(shiny) if shiny_url: path foutput/{p[name]}_shiny.png download_image(shiny_url, path)在main函数末尾调用download_shiny_images(raw_data)这样就能把烈空坐、基格尔德等宝可梦的闪光形态图片保存到本地。对于喜欢做图鉴工具或头像素材库的同学来说这个功能非常实用。4.6 结果说明与分析思路跑完脚本之后你会得到一张折线图和若干张闪光图片。折线图可以直观看到不同宝可梦的种族值分布。以烈空坐和基格尔德举例两者都是传说级宝可梦种族值总和都比较高。烈空坐拥有飞行属性速度方面比较突出。基格尔德是龙/地面属性防御端往往有不错表现。这里需要说明最终数值以接口返回为准不同形态的基格尔德比如 10% 形态、50% 形态、完全体形态种族值会不同。本文示例中的zygarde名称对应的是基础形态如果你需要其他形态可以查阅 PokeAPI 的文档使用完整的形态名称例如zygarde-50-power-construct等。5. 常见问题与排查思路实际运行过程中最常见的几个问题如下问题现象常见原因解决思路请求超时网络不稳定或接口响应慢增加 timeout添加重试机制返回 404宝可梦名称拼写错误检查名称是否符合 PokeAPI 命名规范KeyError: stats响应结构异常先打印resp.json()看一下字段matplotlib 中文乱码系统缺少中文字体配置字体或改用英文标签图片路径无内容接口未返回闪光图片打印sprites字段检查 URL 是否为空5.1 请求超时怎么办网络问题是最常见的。建议在fetch_pokemon中增加重试逻辑def fetch_pokemon_with_retry(name, retries3): for i in range(retries): try: return fetch_pokemon(name) except requests.RequestException as e: print(f第 {i 1} 次请求失败: {e}) time.sleep(2) raise RuntimeError(f请求 {name} 失败超过 {retries} 次)对接口请求加入重试和退避是生产级爬虫的基础要求。5.2 matplotlib 中文乱码怎么解决很多 Windows 和 Linux 环境默认字体不支持中文图表会显示成方块。在代码开头加一段字体配置即可plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, WenQuanYi Zen Hei] plt.rcParams[axes.unicode_minus] False不同系统的字体名不一样你可以按需替换。如果目标机器上没有这些字体建议图表英文标签避免乱码问题。5.3 官方字段变化如何处理API 结构偶尔会有调整最好的排查方法是打印原始 JSONdata fetch_pokemon(rayquaza) print(data.keys())这样你可以看到返回的所有一级字段再逐层深入查找。不要凭感觉猜测字段名。6. 最佳实践与工程建议6.1 控制请求频率与缓存PokeAPI 是免费公开接口但不代表可以随意高频请求。在实际开发中建议每次请求之间至少间隔 0.5 秒。对已经获取的数据做本地缓存例如保存为 JSON 或 CSV避免重复请求。如果只是学习控制的请求量尽量小不要做大规模批量抓取。缓存示例import json import os CACHE_FILE pokemon_cache.json def load_cache(): if os.path.exists(CACHE_FILE): with open(CACHE_FILE, r, encodingutf-8) as f: return json.load(f) return {} def save_cache(cache): with open(CACHE_FILE, w, encodingutf-8) as f: json.dump(cache, f, ensure_asciiFalse, indent2)这样即使脚本中断也可以从缓存中恢复数据。6.2 代码结构要分层本文把接口请求、数据解析、主流程分成不同函数甚至不同文件目的就是降低耦合。未来如果要加数据库存储、Web 服务、定时任务都可以在不改动其他模块的前提下完成。推荐的分层思路接口层负责所有 HTTP 通信。解析层把原始 JSON 转换成业务对象。数据层负责本地缓存、CSV 导出、数据库写入。展示层负责图表绘制、报表生成。6.3 异常处理要完整网络请求至少要考虑以下异常连接超时。DNS 解析失败。HTTP 状态码错误。JSON 解析失败。不要用空except吞掉异常至少要打印日志。推荐使用logging模块记录运行日志import logging logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__)6.4 数据伦理与合法使用虽然 PokeAPI 是公开接口但在项目开发里仍然要注意阅读接口提供方的服务条款。不要用接口做商业用途而不署名。不要高频请求影响服务稳定性。如果数据用于自己的分析学习没有太多限制。这些习惯同样适用于企业内外部 API 的使用。保持最小权限和合理使用是开发者基本素养。7. 总结与后续学习方向通过本文的实战你已经完成了从请求公开接口到可视化输出的完整链路。我们做的事情包括使用requests调用 PokeAPI 获取宝可梦 JSON 数据。解析嵌套的types、stats、sprites字段。使用pandas对数据进行结构化处理。使用matplotlib绘制种族值对比图。下载闪光宝可梦图片到本地。掌握请求超时、中文乱码等常见问题的排查方法。这套思路并不仅限于宝可梦数据。任何公开 API只要返回标准 JSON都可以用同样的方式做采集、清洗、分析和展示。下一步如果你想继续深入可以考虑这几个方向把数据存入 SQLite 或 MySQL做更复杂的条件查询。基于宝可梦属性做攻防克制关系分析。构建一个 Web 页面把图表和图片展示出来。加入更多宝可梦计算种族值排名输出 PDF 报表。技术练手的关键是“提出问题然后动手解决”。今天你可以分析烈空坐和基格尔德的种族值明天就能把同样的方法迁移到其他数据集上。如果这篇文章对你有帮助欢迎收藏备用。你也可以把代码跑起来截图保存你的分析结果试着加入更多你喜欢的宝可梦继续扩展这个数据小项目。
返回列表