ランダムな猫ちゃんの画像を表示するPythonアプリを作成してみよう!
準備
The Cats APIキーの取得
まずは猫ちゃんの画像をランダムに送ってくれるサービスのAPIキーを取得する。無料なので安心だ。
以下のURLにアクセス
https://thecatapi.com/
Get Your API KEY
ボタンを押す
Get FREE ACCESSを押す
トークンを受信可能なメールアドレス
目的(ここでは Random Cat Viewer)として
SUBMITを押す。
指定したURLにAPI Keyが届くのでコピーしてテキストエディタにでも貼り付けておく。
requests,pillowのインストール
通信を便利に行えるようにするrequestsモジュールをインストール
$ pip install requests requests
またjpgを表示するにはpillowモジュールが必要となる。環境にインストールしておこう。
$ pip install requests pillow
(参考)
作成
レスポンスの確認
まずはCat APIのレスポンスを確認してみよう。cat.pyとして以下を作成する。
CAT_API_KEYの部分には先程エディタに貼り付けておいたAPI KEYを記述すること
import requests
import pprint
# 猫API設定
CAT_API_URL = "https://api.thecatapi.com/v1/images/search"
CAT_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
def get_random_image_url():
"""猫の画像URLを取得"""
headers = {"x-api-key": CAT_API_KEY}
response = requests.get(CAT_API_URL, headers=headers)
if response.status_code == 200:
data = response.json()
if data:
return data
return None
pprint.pprint(get_random_image_url())
実行してみよう。以下のようなdictが表示されれば成功だ。(毎回違う)
$ py cat.py
[{'breeds': [],
'height': 332,
'id': 'bh3',
'url': 'https://cdn2.thecatapi.com/images/bh3.jpg',
'width': 491}]
どうやら、’url’というキーで画像のURLを取得できるようだ。
ルートが配列になっているので画像のURLは以下のコードで取得できる。
import requests
# 猫API設定
CAT_API_URL = "https://api.thecatapi.com/v1/images/search"
CAT_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
def get_random_image_url():
"""猫の画像URLを取得"""
headers = {"x-api-key": CAT_API_KEY}
response = requests.get(CAT_API_URL, headers=headers)
if response.status_code == 200:
data = response.json()
if data:
return data[0]['url']
return None
print(get_random_image_url())
完成
それでは、画像を取得する処理とウィジットを配置する処理を追記しよう。
import requests
import tkinter as tk
from PIL import Image,ImageTk
import io
# 猫API設定
CAT_API_URL = "https://api.thecatapi.com/v1/images/search"
CAT_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
def get_random_image_url():
"""猫の画像URLを取得"""
headers = {"x-api-key": CAT_API_KEY}
response = requests.get(CAT_API_URL, headers=headers)
if response.status_code == 200:
data = response.json()
if data:
return data[0]['url']
return None
def update_cat_image():
image_url = get_random_image_url()
if image_url:
response = requests.get(image_url)
if response.status_code == 200:
# 画像をバイナリデータとして取得
image_data = io.BytesIO(response.content)
# バイナリデータから画像を作成
pil_image = Image.open(image_data)
# 縦横比を保持したリサイズ
max_size = 500
# thumbnail()メソッドで比率を保ったまま、max_sizeを超えない範囲で縮小
pil_image.thumbnail((max_size, max_size))
# Tkinterで表示可能な形式に変換
tk_image = ImageTk.PhotoImage(pil_image)
# label_imageに画像を設定
label_image.config(image=tk_image)
# tk_imageがガーベッジコレクションされないように保持
label_image.image = tk_image
# メッセージの更新
label_message.config(text="新しい猫を表示しました!")
else:
label_message.config(text="画像の取得に失敗しました。")
else:
label_message.config(text="猫の画像を取得できませんでした。")
# Tkinterアプリ設定
root = tk.Tk()
root.geometry('500x700')
root.title("ランダム猫画像表示アプリ")
# ウィジェット配置
label_message = tk.Label(root,text="クリックして猫画像を取得!", font=("Arial", 14))
label_message.pack(pady=10)
label_image = tk.Label(root)
label_image.pack(padx=10,pady=10)
button_get_image = tk.Button(root,text="新しい猫を見る", command=update_cat_image, font=("Arial", 12))
button_get_image.pack(pady=10)
# 初期画像を設定
update_cat_image()
# mainループ
root.mainloop()
ポイント解説
途中以下の処理があるが、この部分が冗長だとは感じなかっただろうか?
label_image.config(image=tk_image)
label_image.image = tk_image
なぜ2つの行が必要か?
label_image.config(image=tk_image)
は、実際にウィジェットに表示される画像を設定するlabel_image.image = tk_image
は、表示される画像がガーベジコレクションで削除されないように参照を保持する。
Label
ウィジェットに画像を設定しただけでは、Python がその画像オブジェクトを解放することがある。特に、画像が表示されるときに参照が切れると、画像が正しく表示されないということが起こる。label_image.image = tk_image
を使うことで、画像がメモリに保持され、ガーベジコレクションから削除されることを防ぐことができるのだ。
コメント