さて、今回から「PokeAPI」を使ってポケモンの情報が表示されるようにしてみようか!
ところで、PokeAPIはどんな感じのデータが取れるの??
例えば「ピカチュウ」はIDが「25」だから、「https://pokeapi.co/api/v2/pokemon/25」で中身を見ることができるよ
うおぅ、文字だらけ...!!
PokeAPIみたいに「Web API」はすごい量のJSONなことが多いから、分析していくのは苦労しそうでしょ
だから今回は、その中の一部だけをかい摘んで使っていくね
了解!!まずはスクレイピングの時みたいに「requests」を使うんかな??
そうだね!
じゃあ次のプログラムを追加して、内容を表示してみよう
import requests # 追加を忘れずに!!
# 途中は省略
if search_btn:
poke_id = None # 追加
poke_name = None # 追加
if user_input in NAME_TO_ID:
poke_name = user_input # 入力内容を名前にする
poke_id = NAME_TO_ID[user_input]
elif user_input in ID_TO_NAME:
poke_name = ID_TO_NAME[user_input]
poke_id = user_input # 入力内容をIDにする
# この条件部分を追加
if poke_id is not None: # IDを取得しなかった場合にエラーが出ないようにする
api_url = f"https://pokeapi.co/api/v2/pokemon/{poke_id}"
res = requests.get(api_url)
st.write(res)
else:
st.error("その名前やIDのポケモンは見つかりませんでした。")
あ!なんか「<Response [200]>」って出てきた!
さっきブラウザで見た時みたいに大量に文字が出てくるのかと思った
これは、指定したURLでwebサイトへリクエストを送った時に情報が正しく返ってきたっていう合図だよ!もしちゃんと返ってこない場合は「404」とか「500」って返ってくるんだ
そういえば、たまにホームページを開いた時に「404エラー」みたいなのが表示される時があるから、それと一緒かな
そうだね!だから今回の処理を作る時は、返ってきた情報が「200」だった時に処理をするって流れになるよ
「requests」で受け取った情報は「json」ライブラリで扱えるから、まずは「たかさ」と「おもさ」を取り出してみよう!
import json # 追加を忘れずに!!
# 途中は省略
if poke_id is not None:
api_url = f"https://pokeapi.co/api/v2/pokemon/{poke_id}"
res = requests.get(api_url)
# ここから追加
if res.status_code == 200:
data = res.json()
height = data["height"] / 10
weight = data["weight"] / 10
st.write(f"たかさ: {height} m")
st.write(f"おもさ: {weight} kg")
「たかさ」と「おもさ」が表示されてるね!
でも、両方とも10で割らないとけないのは手間だね
それは海外の人が作ってて、そこの国の基準になってるからだね
web APIを扱う時はよくあることだからデータはしっかり観察しようね
はーい!
じゃあ次は「タイプ」と「能力(種族値)」を表示しようか
だけどその前に、得られる情報は英語表記だから日本語に変換出来る辞書型の定数を用意しよう
# タイプと能力値の日本語辞書
TYPES = {
"normal": "ノーマル", "fire": "ほのお", "water": "みず", "electric": "でんき",
"grass": "くさ", "ice": "こおり", "fighting": "かくとう", "poison": "どく",
"ground": "じめん", "flying": "ひこう", "psychic": "エスパー", "bug": "むし",
"rock": "いわ", "ghost": "ゴースト", "dragon": "ドラゴン", "dark": "あく",
"steel": "はがね", "fairy": "フェアリー"
}
STATS = {
"hp": "HP", "attack": "こうげき", "defense": "ぼうぎょ",
"special-attack": "とくこう", "special-defense": "とくぼう",
"speed": "すばやさ"
}
これはimportしているプログラムのすぐ下くらいに配置したら良いよね!
どこに何を配置したら良いかイメージが出来てきてるね
じゃあ、その調子で表示内容を追加してみようか!
if res.status_code == 200:
data = res.json()
height = data["height"] / 10
weight = data["weight"] / 10
# タイプを日本語に変換
types = [TYPES[t["type"]["name"]] for t in data["types"]]
# 種族値を日本語に変換
stats = {STATS[s["stat"]["name"]]: s["base_stat"] for s in data["stats"]}
st.header(f"{poke_name}")
st.write(f"ID: {poke_id}")
st.write(f"タイプ: {', '.join(types)}")
st.write(f"たかさ: {height} m")
st.write(f"おもさ: {weight} kg")
st.subheader("種族値")
for stat_name, stat_val in stats.items():
st.write(f"- {stat_name}: {stat_val}")
ポケモンのタイプは「types」、種族値は「stats」で受け取れるんだね!
この2つは複数の情報を持ってるから、内包表記で1つずつ日本語に変換してるってことか
そういうことだね!プログラムを更新した後に検索して結果を見てみると...
おおー!バッチリだね!!だけど、文字だけだと図鑑って感じはしないなぁ
じゃあ次の項目で、より図鑑っぽくするために画像や鳴き声を追加しよう!
この時点での全体のプログラム
import streamlit as st
import json
import requests
# タイプと能力値の日本語辞書
TYPES = {
"normal": "ノーマル", "fire": "ほのお", "water": "みず", "electric": "でんき",
"grass": "くさ", "ice": "こおり", "fighting": "かくとう", "poison": "どく",
"ground": "じめん", "flying": "ひこう", "psychic": "エスパー", "bug": "むし",
"rock": "いわ", "ghost": "ゴースト", "dragon": "ドラゴン", "dark": "あく",
"steel": "はがね", "fairy": "フェアリー"
}
STATS = {
"hp": "HP", "attack": "こうげき", "defense": "ぼうぎょ",
"special-attack": "とくこう", "special-defense": "とくぼう",
"speed": "すばやさ"
}
# タイトル・説明
st.title("ポケモン図鑑")
st.write("これから段階的に機能を増やしていこう!")
# JSONファイルを読み込み(日本語名 → ID)
with open("poke_dict.json", "r", encoding="utf-8") as f:
NAME_TO_ID = json.load(f)
# ID → 日本語名 の逆引き辞書も作成
ID_TO_NAME = {str(v): k for k, v in NAME_TO_ID.items()}
# 入力とボタン
user_input = st.text_input("ポケモンの名前またはIDを入力してください")
search_btn = st.button("検索")
# 検索処理
if search_btn:
poke_id = None
poke_name = None
if user_input in NAME_TO_ID:
poke_id = NAME_TO_ID[user_input]
poke_name = user_input
elif user_input in ID_TO_NAME:
poke_id = int(user_input)
poke_name = ID_TO_NAME[user_input]
if poke_id is not None:
api_url = f"https://pokeapi.co/api/v2/pokemon/{poke_id}"
res = requests.get(api_url)
if res.status_code == 200:
data = res.json()
height = data["height"] / 10
weight = data["weight"] / 10
# タイプを日本語に変換
types = [TYPES[t["type"]["name"]] for t in data["types"]]
# 種族値を日本語に変換
stats = {STATS[s["stat"]["name"]]: s["base_stat"] for s in data["stats"]}
st.header(f"{poke_name}")
st.write(f"ID: {poke_id}")
st.write(f"タイプ: {', '.join(types)}")
st.write(f"たかさ: {height} m")
st.write(f"おもさ: {weight} kg")
st.subheader("種族値")
for stat_name, stat_val in stats.items():
st.write(f"- {stat_name}: {stat_val}")
else:
st.error("その名前やIDのポケモンは見つかりませんでした。")
