ポケモンAPIを使ってIDから画像を取得する！

## 概要
最近長期インターンシップに参加することが決まり，事前課題の提出を求められました．
事前課題の内容はポケモンAPIを叩いてIDを入力したらそれに対応したポケモンの画像を返すというもののプログラムを提出せよって感じでした．

私の現在の技術力では2時間程度で実装できました．その流れとコードの解説を残しておきたいと思います．

https://pokeapi.co/

## 使ってみた

実際にIDを入力して得た出力結果の画像がこんな感じです．
IDに対応したポケモンの名前と画像URLと画像そのものを出力しています．
ID:393はポッチャマに対応するのでポッチャマがいます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3888054/1ed7fb03-d2fa-8000-fc88-d3ad967a93d3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3888054/0cabe013-9ca7-bd06-df4d-6bd2f5e4e7c2.png)

## poke APIの説明
ポケモンAPIは誰でも利用できて登録も一切不要でした．初学者がAPIを使った演習をするのには便利なAPIの1つだと思います．
ポケモンAPIはAPIの中でもREST APIと呼ばれる種類のようです．
以下の記事を読むと理解が深まりやすいと思います．

https://tech.012grp.co.jp/entry/rest_api_basics

https://qiita.com/masato44gm/items/dffb8281536ad321fb08

簡単にまとめると，
➀統一インターフェース
GET，POST，PUT，DELETEなどのHTTPメソッドを使って，結果はJSON形式で返しますみたいな感じ

②アドレス可能性
URLでAPIを叩ける感じ

③接続性
ハイパーリンクを含んだページを返すことができる．正直よくわからん

④ステートレス性
やり取りが1回ごとに完結する感じ
例えばfor文やwhile文で何回もリクエストを送ると，それに対してまとめて一括ではなくて1回ずつ応答を返すという感じ．つまり叩きすぎると怒られるやつ

といった具合ですこれがRESUTfulなシステムであり，REST APIと呼ばれているそうです．

## コード
### リクエスト送信

```python
url = "https://pokeapi.co/api/v2/pokemon/"

print('IDを入力してください。')
poke_id = input('>> ')

# urlにIDを付与
url = url + poke_id

# APIにリクエストを送信
response = requests.get(url)
```
https\://pokeapi.co/api/v2/pokemon/[ID or name]
このURLのIDかnameの欄にIDを入力してリクエストを送ります．
例えば
https\://pokeapi.co/api/v2/pokemon/1
とするとフシギダネの情報を
https\://pokeapi.co/api/v2/pokemon/393
とするとポッチャマの情報をJSON形式で返してくれます．

### 存在しないIDのエラー処理
```python
# 存在しないIDの時はエラーメッセージを表示
if response.status_code == 404:
    print(f"ポケモンID {poke_id} は存在しません。")
```
現在ポケモンは1050匹くらいいるらしいです．基本的にpoke APIのIDはポケモン図鑑の番号とリンクしているのですが，どうやら例外がいるようです．
例えばID：10041だとメガギャラドス，ID：10103だとアローラロコンといった具合です．公式ドキュメントにIDリストのようなものはパッと見だと見つからないので先にIDを取得してみるのもアリかもしれません．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3888054/b3a08349-094e-0076-3f03-ffde1b76619c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3888054/c2eba5c9-5243-3c23-f861-f5e708228fa2.png)

自分はDP，HGSS，BWの世代なので，アローラのすがたや〇〇進化みたいなものが増えていてびっくりしました．
この時点で1ポケモンに対して1IDではなく，ノーマル姿，〇〇姿，〇〇進化に対して1つずつIDが付与されていることが分かります．
最初は入力されたIDを1～1050くらい(ポケモン番号の最大数)までの範囲で入力制限をかけて，範囲外の番号が入力されたらエラーを吐くようにif文を書こうとしていました．しかしそれだと例外のポケモンが処理できなくなります．
そこで入力されたIDのままリクエストを送り，存在しないIDの場合は404エラーが返ってくることを利用して処理する方針に変えました．

### 存在するIDの時の処理

```python
else:
    # JSONレスポンスを取得
    response = response.json()

    # ID(int)
    id = response['id']
    # 名前(string)
    name = response['name']
    # 画像(string)
    image_url = response['sprites']['front_default']
```
レスポンスがJSONで返ってきます．JSONの中身は公式ドキュメントに書いてあります．いわゆるポケモン図鑑に書いてあるような細かいデータがほとんど返ってきます．必要に応じてデータを取得しておきます．今回はID，名前，画像の3つを得ました．画像は前向き，後ろ向き(ポケモンバトルの自分側か相手側の向きかみたいな違い)や日が当たっているかどうかみたいに色々選べましたが，今回は前向きの一番普通の画像を取得しました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3888054/293451b0-eb7a-0726-da0f-843840ee6227.png)

### 取得したデータの表示
```python
    print("ID："+str(id))
    print("名前："+name)
    print("画像URL："+image_url)

    # 画像URLを読み取って表示する
    image_response = requests.get(image_url)
    img_data = BytesIO(image_response.content)
    img = Image.open(img_data)
    plt.imshow(img)
    plt.axis('off')  # 軸を表示しない
    plt.show()
```
表示しているだけです．ここに関しては自分でもよくわかってないというか，こういう処理で画像を表示できますの通りに書いただけです()
このコードがGoogle Colaboratoryという環境で実行しました．そのためどうやら画像表示のライブラリのどれかが使えないらしい．(img.show()だったかな?)調べてみるとGoogle Colaboratoryでの画像表示はめんどくさいと色々出てきます．
今回はインターン先がこの環境でコードを書いてほしいと指定があったので別のアプローチを取りました．普通にmatplotlibでグラフ上に表示し，グラフの軸は消すという意味わからん表示方法になりました．これに関してはもっと良い方法があるのではないかと思います．
また，ポケモンの名前についてですが，英名ですね．僕もわかっています．これは返ってくるJSONに日本語名がないのです．日本で生まれたポケモンなのに日本語名がないという不思議さですがあるものを使うしかないので日本語表記は断念．

https\://pokeapi.co/api/v2/pokemon/[ID or name]
https\://pokeapi.co/api/v2/pokemon-species/[ID or name]
今回使ったのは上で，下を利用すれば一応出せなくはないみたい．参考記事を下に載せときます．
インターン先から名前の表示は求められていなかったのでまあ英名でも十分だろうと思い，ここまでは実装しませんでした．

https://qiita.com/jinto/items/9d0d9df30dded1e61015


### 全体像
```python
import requests
from PIL import Image
from io import BytesIO
import matplotlib.pyplot as plt

url = "https://pokeapi.co/api/v2/pokemon/"

print('IDを入力してください。')
poke_id = input('>> ')

# urlにIDを付与
url = url + poke_id

# APIにリクエストを送信
response = requests.get(url)


# 存在しないIDの時はエラーメッセージを表示
if response.status_code == 404:
    print(f"ポケモンID {poke_id} は存在しません。")
else:
    # JSONレスポンスを取得
    response = response.json()

    # ID(int)
    id = response['id']
    # 名前(string)
    name = response['name']
    # 画像(string)
    image_url = response['sprites']['front_default']

    print("ID："+str(id))
    print("名前："+name)
    print("画像URL："+image_url)

    # 画像URLを読み取って表示する
    image_response = requests.get(image_url)
    img_data = BytesIO(image_response.content)
    img = Image.open(img_data)
    plt.imshow(img)
    plt.axis('off')  # 軸を表示しない
    plt.show()
```
## 終わりに
いかがだったでしょうか．
Google周りのAPIやLINE周りのAPIは触ったことがあったのですが，このようなAPIを触ったのは初めてだったので色々勉強しながらの作成になりました．長期インターンはまだこれからで，これはあくまで事前課題なのでさらに技術力が成長できそうなのが楽しみです．