如何使用 Python 构建菜谱查找应用程序

网络上充斥着大量的食谱,链接和广告层出不穷,要找到一份完美的食谱可谓是一项挑战。构建一个菜谱搜索应用程序,可以提供定制化的、用户友好的体验以及一致的设计,从而消除所有无关的结果和干扰。

通过构建这个应用程序,您将提升在 HTTP 请求、API 密钥管理、图像处理以及构建图形用户界面(包括动态 GUI 更新)方面的技能。

安装 Tkinter、Requests、Pillow 和 Webbrowser 模块

为了构建菜谱搜索应用程序,您需要 Tkinter、Requests、PIL 和 Webbrowser 模块。 Tkinter 允许您创建桌面应用程序。 它提供了各种小部件,使 GUI 开发变得更容易。 要安装 Tkinter,请打开终端并运行:

pip install tkinter

Requests 模块简化了发送 HTTP 请求并返回包含编码和状态等信息的响应对象的过程。您可以使用它来获取来电显示信息、创建网站状态检查器、货币转换器或新闻应用程序。要安装 Requests 模块,请打开终端并运行:

pip install requests

Pillow 库是 Python Imaging Library (PIL) 的一个分支,它提供图像处理功能,有助于编辑、创建、转换文件格式和保存图像。要安装 Pillow 模块,请打开终端并运行:

pip install Pillow

Webbrowser 模块可以帮助您在默认浏览器中打开任何链接。它是 Python 标准库的一部分,因此您无需单独安装它。

生成用于食谱搜索的 Edamam API 密钥

要生成 Edamam 食谱搜索 API 密钥,请按照以下步骤操作:

  • 访问Edamam 并点击“注册 API”按钮。填写详细信息,然后选择您的计划为“食谱搜索 API – 开发人员”。
  • 登录您的帐户,点击“帐户”按钮,然后点击“转到仪表板”按钮。
  • 之后,点击“应用程序”选项卡,最后点击“菜谱搜索 API”旁边的“查看”按钮。
  • 复制应用程序 ID 和应用程序密钥并存储它们,以便在您的应用程序中使用。

构建获取前 5 名食谱的功能

您可以在GitHub 存储库中找到使用 Python 构建菜谱查找应用程序的完整源代码。

导入必要的模块。定义 get_top_5_recipes() 方法,该方法用于检索用户搜索的前五个菜谱的标题、图像和链接。使用 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 =  # 您的 app_id
        app_key =  # 您的 app_key

创建一个名为 params 的字典,其中包含您必须作为 API 请求的一部分传递的不同参数。将 qapp_idapp_key 的键值对设置为您之前获得的值。设置 fromto 参数以反映您希望查看的结果数量。

结合 API URL 和参数字典,向 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 键以及是否包含搜索结果。 如果是,则遍历搜索结果并逐个提取食谱信息。向图像 URL 发送 GET 请求,并将 stream 参数设置为 True,以便允许流式传输图像数据。

使用 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)

构建应用程序的结构

定义三个标签来显示食谱标题、图像和食谱链接。设置您希望放置它的父窗口、您希望显示的文本以及它应该具有的字体样式。要显示图像,请将图像属性设置为 photo_image。将链接标签中的光标选项设置为 hand2,使其可点击。

绑定链接和鼠标左键单击事件以调用 open_link() 函数。使用 pack 方法组织所有小部件,将其水平居中并根据需要添加填充。将标题、图像和链接附加到三个不同的列表。

                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_labels 列表中的每个标签。

调用 pack_forget() 方法从显示中删除标签,但保持小部件对象完整。

清除 recipe_labels 列表中的新数据。对图像和链接也重复此过程。定义一个 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="输入食谱名称:", 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="搜索食谱",
    font=("Helvetica", 12, "bold"),
    command=get_top_5_recipes,
)
search_button.pack(pady=10)

创建一个白色背景的画布,以显示保存食谱信息的小部件。将其组织到窗口的左侧,在两个方向上占用框架中的所有空间,并在调整大小时将其扩展。

为画布创建一个垂直滚动条并将其放置在其右侧。将 scrollbar.set 方法链接到 canvas.yview 方法,这样滚动滚动条就会滚动画布内容。

在画布内创建一个框架作为食谱项的容器,锚定在窗口的左上角。绑定 <Configure> 事件,以确保框在其内容更改或调整大小时可以正确滚动。

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()

将所有内容放在一起,只需单击一个按钮即可发现美食。

食谱查找器应用程序的输出

当您运行该程序并将菜肴输入为“鸡肉汉堡”时,您将获得前五个结果。 它包含您输入的菜肴的标题、图像和食谱链接。 单击该链接后,默认网络浏览器将打开食谱链接。 向下滚动时,内容大小保持不变,并水平居中显示各种结果。

增强食谱查找器应用程序

为了增强您的食谱查找器应用程序,您可以根据不同的偏好实施过滤和排序。您可以根据饮食偏好、烹饪时间和菜系来过滤菜肴,并按任意顺序排序。

创建一个功能,为您最喜欢的食谱添加书签,以便稍后查看,并提供在社交媒体上分享它们的选项。您可以创建一个类别来发现搜索最多的菜肴、添加书签最多的菜肴等。

结合您的编程技能和 API 的强大功能,您可以进一步将这个基本应用程序转换为一个成熟的应用程序。