Pythonを使ってレシピ検索アプリを構築する方法

何百ものリンクや広告が散りばめられたインターネット全体にレシピがあふれているため、完璧なレシピを見つけるのは大変です。レシピ検索アプリを構築すると、カスタマイズされたユーザーフレンドリーなエクスペリエンスと一貫したデザインが得られ、無関係な結果や気を散らすものがすべて排除されます。

このアプリを構築することで、HTTPリクエスト、APIキー管理、画像操作、動的GUI更新を含むグラフィカルユーザーインターフェースの構築のスキルを磨くことができます。

Tkinter、Requests、Pillow、Webbrowserモジュールのインストール

レシピ検索アプリを構築するには、Tkinter、Requests、PIL、Webbrowserモジュールが必要です。Tkinterを使用すると、デスクトップアプリケーションを作成できます。GUIを開発しやすくするさまざまなウィジェットを提供します。Tkinterをインストールするには、ターミナルを開いて次を実行します。

pip install tkinter

Requestsモジュールを使用すると、簡単にHTTPリクエストを行い、エンコーディングやステータスなどのデータを含むレスポンスオブジェクトを返します。発信者ID情報を取得したり、Webサイトステータスチェッカー、通貨コンバーター、ニュースアプリケーションを作成したりするために使用できます。Requestsモジュールをインストールするには、ターミナルを開いて次を実行します。

pip install requests

Python Imaging Library(PIL)のフォークであるPillowライブラリは、ファイル形式の編集、作成、変換、画像の保存に役立つ画像処理機能を提供します。Pillowモジュールをインストールするには、ターミナルを開いて次を実行します。

pip install Pillow

Webbrowserモジュールは、デフォルトのブラウザで任意のリンクを開くのに役立ちます。Python標準ライブラリの一部です。したがって、外部からインストールする必要はありません。

レシピ検索用のEdamam APIキーを生成する

Edamam Recipe Search APIキーを生成するには、次の手順に従います。

  1. Edamamにアクセスし、Signup APIボタンをクリックします。詳細を入力し、プランとしてRecipe Search API - Developerを選択します。
  2. アカウントにログインし、the Accountsボタンをクリックしてから、Go to Dashboardボタンをクリックします。
  3. その後、Applicationsタブをクリックし、最後にRecipe Search APIの横にあるViewボタンをクリックします。
  4. Application IDApplication Keysをコピーして、アプリケーションで使用するために保存します。

上位5つのレシピを取得する機能の構築

このGitHubリポジトリでPythonを使用してレシピ検索アプリを構築するためのソースコード全体を見つけることができます。

必要なモジュールをインポートします。メソッドget_top_5_recipes()を定義します。これは、ユーザーが検索した料理の上位5つのレシピのタイトル、画像、リンクを取得します。get()を使用して、ユーザーが検索した料理の名前を抽出します。

ユーザーがレシピ名を入力した場合、Edamam APIのレシピ検索エンドポイントの基本URLを定義します。前にコピーしたapp_idapp_keyを渡して、APIリクエストを認証および認可します。

import tkinter as tk
import requests
from PIL import Image, ImageTk
import webbrowser
def get_top_5_recipes():
recipe_name = entry_recipe_name.get()
if recipe_name:
api_url = "https://api.edamam.com/search"
app_id = # Put your app id for edamam api
app_key = # Put your app key for edamam api

APIリクエストの一部として渡す必要があるさまざまなパラメータを含む辞書paramsを作成します。qapp_id、およびapp_keyのキーと値のペアを、前に取得した値に設定します。表示する結果の数を反映するようにfromtoのパラメータを設定します。

API URLとparams辞書を組み合わせて、Edamam APIにGETリクエストを送信します。レスポンスを格納してJSON形式で抽出します。clear_recipe_list()を呼び出して、以前のリクエストから画面に表示されているレシピをクリアします。

params = {
"q": recipe_name,
"app_id": app_id,
"app_key": app_key,
"from": 0,
"to": 5,
}
response = requests.get(api_url, params=params)
data = response.json()
clear_recipe_list()

抽出されたJSONデータにキーhitsが存在し、検索結果が含まれているかどうかを確認します。存在する場合は、検索結果を反復処理して、レシピ情報を1つずつ抽出します。streamパラメータをTrueに設定して画像データのストリーミングを許可するように設定して、画像URLにGETリクエストを送信します。

PillowモジュールのImageクラスを使用して、受信した画像を開きます。高品質のサイズ変更のためにLanczosリサンプリング方法を使用して、高さおよび幅が200ピクセルになるようにサイズを変更します。これをTkinter互換のPhotoImageに変換して、グラフィカルユーザーインターフェースに表示します。

if "hits" in data and data["hits"]:
for i, hit in enumerate(data["hits"]):
recipe = hit["recipe"]
recipe_list.append(recipe)
recipe_name = recipe["label"]
recipe_link = recipe["url"]
image_url = recipe["image"]
image_response = requests.get(image_url, stream=True)
image = Image.open(image_response.raw)
image = image.resize((200, 200), Image.LANCZOS)
photo_image = ImageTk.PhotoImage(image)

アプリケーションの構造を構築する

レシピのタイトル、画像、レシピへのリンクを表示するために3つのラベルを定義します。配置する親ウィンドウ、表示するテキスト、使用するフォントスタイルを設定します。画像を表示するには、image属性をphoto_imageに設定します。リンクラベルのcursorオプションをhand2に設定してクリックできるようにします。

リンクと左マウスクリックイベントをバインドして、open_link()関数を呼び出します。packメソッドを使用してすべてのウィジェットを整理し、水平方向に中央揃えにして必要に応じてパディングを追加します。タイトル、画像、リンクを3つの異なるリストに追加します。

recipe_title_label = tk.Label(
canvas_frame,
text=f"{i+1}. {recipe_name}",
font=("Helvetica", 12, "bold"),
)
recipe_title_label.pack(pady=(5, 0), anchor=tk.CENTER)
image_response = requests.get(image_url, stream=True)
image = Image.open(image_response.raw)
image = image.resize((200, 200), Image.LANCZOS)
photo_image = ImageTk.PhotoImage(image)
image_label = tk.Label(canvas_frame, image=photo_image)
image_label.image = photo_image
image_label.pack(pady=(0, 5), anchor=tk.CENTER)
link_label = tk.Label(
canvas_frame, text=recipe_link, fg="blue", cursor="hand2"
)
link_label.pack(pady=(0, 10), anchor=tk.CENTER)
link_label.bind(
"<Button-1>", lambda event, link=recipe_link: open_link(link)
)
recipe_labels.append(recipe_title_label)
recipe_images.append(photo_image)
recipe_links.append(link_label)

clear_recipe_list()メソッドを定義して、前のリクエストによって生成された画面のコンテンツ全体をクリアします。レシピリストのコンテンツをクリアし、recipe_labelリストの各ラベルを反復処理します。

pack_forget()メソッドを呼び出してラベルをディスプレイから削除しますが、ウィジェットオブジェクトはそのままにします。

新しいデータ用にrecipe_labelsリストをクリアします。このプロセスを画像とリンクにも繰り返します。レシピのリンクを既定のWebブラウザで開くopen_link()メソッドを定義します。

def clear_recipe_list():
recipe_list.clear()
for label in recipe_labels:
label.pack_forget()
recipe_labels.clear()
for image_label in recipe_images:
image_label.pack_forget()
recipe_images.clear()
for link_label in recipe_links:
link_label.pack_forget()
recipe_links.clear()
def open_link(link):
webbrowser.open(link)

Tkinterのルートウィンドウを初期化します。アプリケーションのタイトル、寸法、背景色を設定します。フレームウィジェットを定義し、その親要素と背景色を設定します。ラベル、エントリ、検索ボタンを作成します。packメソッドを使用してすべてのウィジェットを整理し、必要に応じてパディングを追加します。

root = tk.Tk()
root.title("Recipe Finder")
root.geometry("600x600")
root.configure(bg="#F1F1F1")
frame = tk.Frame(root, bg="#F1F1F1")
frame.pack(fill=tk.BOTH, expand=tk.YES, padx=20, pady=20)
label_recipe_name = tk.Label(
frame, text="Enter Recipe Name:", font=("Helvetica", 14, "bold"), bg="#F1F1F1"
)
label_recipe_name.pack()
entry_recipe_name = tk.Entry(frame, font=("Helvetica", 12))
entry_recipe_name.pack(pady=5)
search_button = tk.Button(
frame,
text="Search Recipes",
font=("Helvetica", 12, "bold"),
command=get_top_5_recipes,
)
search_button.pack(pady=10)

レシピ情報を保持するウィジェットを表示するために白い背景のキャンバスを作成します。フレームの左側に整理し、フレーム内のすべてのスペースを両方向に取り、サイズ変更時に拡張します。

キャンバスの縦スクロールバーを作成し、その右側に配置します。scrollbar.setメソッドをcanvas.yviewメソッドにリンクして、スクロールバーをスクロールするとキャンバスのコンテンツがスクロールされるようにします。

キャンバス内にフレームを作成してレシピアイテムのコンテナーとして機能させ、ウィンドウの左上にアンカーします。イベントをバインドして、コンテンツが変更またはサイズ変更されたときにボックスが正しくスクロールされるようにします。

canvas = tk.Canvas(frame, bg="white")
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.YES)
scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL, command=canvas.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas.configure(yscrollcommand=scrollbar.set)
canvas_frame = tk.Frame(canvas, bg="white")
canvas.create_window((0, 0), window=canvas_frame, anchor=tk.NW)
canvas_frame.bind(
"<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all"))
)

レシピ、ラベル、画像、リンクのリストを定義します。mainloop()関数は、ウィンドウを閉じるまでPythonにTkinterイベントループを実行してイベントをリッスンするように指示します。

recipe_list = []
recipe_labels = []
recipe_images = []
recipe_links = []
root.mainloop()

すべてをまとめて、ボタンをクリックするだけで料理を発見しましょう。

レシピ検索アプリの出力

プログラムを実行して料理に「チキンバーガー」と入力すると、上位5つの結果が表示されます。入力した料理のタイトル、画像、レシピリンクが含まれています。リンクをクリックすると、既定のWebブラウザでレシピリンクが開きます。スクロールダウンすると、コンテンツサイズは同じままになり、さまざまな結果が水平方向に中央揃えで表示されます。

レシピ検索アプリの強化

レシピ検索アプリを強化するために、さまざまな好みに応じたフィルタリングと並べ替えを実装できます。食事の好み、調理時間、料理によって料理をフィルタリングし、任意の順序で並べ替えることができます。

後で閲覧するために、お気に入りのレシピをブックマークする機能と、ソーシャルメディアで共有するオプションを作成します。最も検索された料理、最もブックマークされた料理などを発見するためのカテゴリを作成できます。

プログラミングスキルとAPIの強力な機能を組み合わせることで、この基本的なアプリケーションを本格的なアプリケーションに変換できます。