ランダムな猫の画像を表示するアプリを作ってみよう!

python

ランダムな猫ちゃんの画像を表示する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 を使うことで、画像がメモリに保持され、ガーベジコレクションから削除されることを防ぐことができるのだ。

          python
          スポンサーリンク
          シェアする
          mjpurinをフォローする

          コメント

          タイトルとURLをコピーしました