0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python 初学者が楽天APIを使って買い物リスト作成アプリを作る(レシピ検索システム編)

Last updated at Posted at 2023-02-13

この記事は以下の続きです

今回は、楽天レシピカテゴリ一覧API と 楽天レシピカテゴリ別ランキングAPIを使って
集めたレシピから検索 ➡ 買い物リストに入れたいレシピを選択する
という機能を作っていきます!

イメージは以下の通り
image.png

このように、検索ワードを入力したら、以下の検索結果が出てきます。
image.png
この中から、以下の様に indexを選択します。
image.png
さらに再度レシピ検索を行うか選択する ところまでを作ります。
image.png

買い物リスト作成アプリの概要はこちら

目次

項番 ページ内リンク
1 レシピ検索機能を作るのに必要な手順
2 準備
3 検索ワードの入力
4 検索ワードがヒットするレシピを見つけて表示
5 indexを選択する
6 レシピ検索を継続するか問う関数をつくる
7 全コード

レシピ検索機能を作るのに必要な手順

  1. ユーザが検索ワードを入力
  2. 検索ワードが「レシピ名」「レシピの材料」から当てはまるレシピをピックアップ
  3. ピックアップしたレシピの「レシピ名」「レシピindex」「何人分のレシピか」「URL」をそれぞれ表示
  4. 何件レシピがヒットしたか表示
  5. 買い物リストに入れたいレシピのindexを選択
  6. 検索を続けるか選択する

この手順を踏んでいきます。

準備

image.png
検索ワードを、こちらのレシピ一覧のB列の「レシピ名」とE列の「レシピ材料」から探すのですが、2列分検索しなくてはいけなくなります。
検索時間を短くしたいので、F列にレシピ名とレシピ材料の列を合体させた列を作り、1列検索すれば良いようにします。

さらにこのあと、ヒットしたレシピの「レシピindex」や「何人分のレシピか」の情報を得たいので、この表自体をリストとして取得しておきます。

列を合体

Python
#必要ライブラリのインポート
import openpyxl 

# ファイルを開き、シートを取得
filename = "test"
wb = openpyxl.load_workbook(filename +".xlsx")
ws = wb.worksheets[0]

for row in ws.iter_rows(min_row=2, max_col=6): #Excelの扱う範囲指定
    #2列目と5列目を足して、6列目に代入
    row[5].value = row[1].value + row[4].value #row[0] = 1列目
#保存
wb.save(filename + ".xlsx") 

これでF列に 「レシピ名」+「レシピ材料」の列が新たにできました。

表をリストとして取得する

Python
#index.レシピ名.URL.人数.レシピ名と材料が一緒になった列のリストを作る
index_name_lists=[]
    #Excelの表の範囲指定
    for row in index_ws.iter_rows(min_row =2, min_col=1, max_col=6):
        index_name =[]
        index_name.append(row[0].value) #index列
        index_name.append(row[1].value) #レシピ名
        index_name.append(row[2].value) #URL
        index_name.append(row[3].value) #人数
        index_name.append(row[5].value) #レシピ名と材料が一緒になった列 

        index_name_lists.append(index_name)

結果は以下です。2重配列のリストになります。
image.png
同じようにこちらの「材料と量」のExcelもリスト化しておきます。index_ing_listsと名前を付けます。
image.png

検索ワードの入力

検索ワードはinput関数を使ってユーザーに入力してもらいます。

Python
word = str(input("検索ワードを日本語で入力してください : "))

次に、isalphaメソッドを使って入力した文字が日本語であるかを判定します。
isalphaメソッドは主に指定したワードが英語で構成されている場合、Trueで返しますが、ひらがな・カタカナ・漢字で構成されていてもTrueを返します。
これを利用します。

参考文献
[解決!Python]文字列が英字(文字)のみで構成されているかどうかを判定するには(isalpha/isasciiメソッド、re.match/re.fullmatch関数)

Python
def input_word():  
    word = str(input("検索ワードを日本語で入力してください : "))
    word_result =  word.isalpha() #ひらがな/カタカナ/漢字が文字判定(True)される。
    if word_result : # Trueの場合、入力ワードを検索する
        search_word(word)
    else:
        print("日本語以外の文字が入力されました") 
        input_word() #Falseの時、再度検索ワード入力

検索ワードがヒットするレシピを見つけて表示

検索ワードがヒットするレシピをレシピindex,レシピ名,URL,何人分,レシピ名+材料が格納されたリストから探します。

Python
title_list = [] #検索件数を把握するためにtitle_list にtitle格納する
    for index_name in index_name_lists: #レシピindex,レシピ名,URL,何人分,レシピ名+材料が格納されたリスト、
         # 検索ワードがレシピ名+材料に含まれるとき        
        if word in index_name[4]:
          
            # それぞれの情報を取得
            index = index_name[0]
            title = index_name[1]
            url = index_name[2]
            people_n = index_name[3]
            title_list.append(title)

            print("+++++++++++++++++++++++++++++++++++++++++")
            print("index : "+ str(index))
            print("レシピ名 : "+ title)
            print(str(people_n)+ " 人分のレシピです")
            print("URL : "+ url)

            #indexが一致する材料と量を表示
            for index_ing in index_ing_lists: #index,材料,量のリスト
                if str(index) in str(index_ing[0]):
                    ingredient = index_ing[1] #材料
                    amount =  index_ing[2] #量          
                    print("{"+ str(ingredient)+""+str(amount)+"}")

    print( str( len(title_list))+ "件のレシピが見つかりました。" )

次に、検索結果がある時、ない時の条件分岐を作ります。

検索結果があれば、次の動作へ
検索結果がなければ、再度検索ワード入力へ戻るようにします。

条件分岐を入れて、関数化するとこちら

Python
def search_word(word):    
    title_list = [] #検索件数を把握するためにtitle_list にtitle格納する
    for index_name in index_name_lists: 
         # 検索ワードと一致した時        
        if word in index_name[4]:
          
            # index と URLを取得する
            index = index_name[0]
            title = index_name[1]
            url = index_name[2]
            people_n = index_name[3]
            title_list.append(title)

            message(index, title, url, people_n)

            for index_ing in index_ing_lists:   #リストとして持っておく
                if str(index) in str(index_ing[0]):
                    ingredient = index_ing[1]
                    amount =  index_ing[2]           
                    print("{"+ str(ingredient)+""+str(amount)+"}")

    print( str( len(title_list))+ "件のレシピが見つかりました。" )

    if len(title_list) == 0: # 検索結果無い場合、検索ワード入力に戻る
        print("検索ワードの文字表記を変えると、検索結果が変わるかもしれません") 
        input_word() #再度検索ワード入力へ戻る
    
    else: # 検索結果がある場合、レシピのindex選択に進む
        input_index() 

indexを選択する

このアプリで使うレシピには、すべてレシピindexという通し番号がついています。
ユーザーに検索結果から買い物リスト化したいレシピのindexを input関数を使って選択してもらいます。

Python
recipe_index = input("買い物リストに入れるレシピの indexを入力してください") 

また、このindexが正の整数であるか?
indexに無い数字を入力していないか?判定するために条件分岐を加えます。
正の整数であるかは、indigistメソッドで判定します。

isdigit メソッドは文字列中のすべての文字が数字であり、かつ 1 文字以上ある場合に、Trueを返します。

isdigitメソッド
print("143234".isdigit())#正の数字(True)
print("-5".isdigit())#負の数(False)
print("1a234".isdigit())#アルファベット入り(False)
print("3.14".isdigit())#小数(False)
print("1234".isdigit())#全角数字(True)

参考文献
文字列の中の文字が数を表す文字かどうかを判定する(isdecimal, isdigit, isnumeric)

さらに、検索できるレシピは全部で2031件なので、2031より上のindexが入力された時は、再度index選択に戻るように条件分岐を追加します。

Python
index_list =[] # レシピindexのリスト    
def input_index(): # 買い物リストに入れるレシピの index が 正しい数字か判定
    recipe_index = input( word_list[3] ) #買い物リストに入れるレシピの indexを入力してください
    index_result = recipe_index.isdigit() # 正の整数か判定
    
    if index_result: #indexが整数のとき
        if 0 <= int(recipe_index) <= 2031: #index内の数字を選択した時にindex_list に追加
            index_list.append(int(recipe_index))
            end()  #レシピ検索を継続するか終了するか選択する関数呼び出し      
        else: #index範囲外の数字が入力された時、もう一度index選択を行う
            print("indexにない数字が入力されました") 
            input_index() 
    else: #数字以外の文字が入力された時、もう一度index選択を行う
        print("数字以外の文字が入力されました") 
        input_index()

レシピ検索を継続するか問う関数をつくる

ユーザーにレシピ検索を継続するか、数字で入力してもらった後に、
indexを選択する関数と同じように、isdigitメソッドを使って入力された文字が整数か判断します。

Python
input_n = input(word_list[6]) #まだレシピ検索しますか?Yes:1,No:0
n_result = input_n.isdigit() # 整数か判定

入力された文字が整数である場合、レシピ検索を続けるか、終了するかで条件分岐を作ります。
さらに、関数化すると以下

Python
def end(): # レシピ検索継続するか 終了するか入力
    input_n = input(word_list[6]) #まだレシピ検索しますか?Yes:1,No:0
    n_result = input_n.isdigit() # 整数か判定
    if n_result:
        
        if int(input_n) == 1: #レシピ検索を継続する場合、レシピ検索関数を再度呼び出し
            input_word()
        
        elif int(input_n) == 0: #レシピ検索を終了する場合以下print
            print("レシピ選択を終わります。 現在" + str(len(index_list)) + "個のレシピが選択されています。")
            print("選択されたレシピ index : " + str(index_list))
            print("それでは買い物リストを作りましょう") 
        else: #0と1以外の数字が入力された時、再度レシピ検索継続か問う
            print("1 or 0で選択してください") 
            end()
    else: #数字以外の文字が入力された時、再度レシピ検索継続か問う
        print("数字以外が入力されました") 
        end()

全コード

Python
#必要ライブラリのインポート
import openpyxl 
import csv
from fractions import Fraction  

#ファイルを開く
ing_wb = openpyxl.load_workbook("recipe_ingredients.xlsx") #レシピの材料と量の一覧表
ing_ws = ing_wb.worksheets[0] 

index_wb = openpyxl.load_workbook("recipe_index.xlsx") #レシピ名、URL、材料、人数分の表一覧
index_ws = index_wb.worksheets[0]
  
#index.レシピ名.URL.人数.レシピ名と材料が一緒になった列のリストを作る
index_name_lists=[]
def create_index_namelist(): 
    
    for row in index_ws.iter_rows(min_row =2, min_col=1, max_col=6):
        index_name =[]
        index_name.append(row[0].value) #index列
        index_name.append(row[1].value) #レシピ名
        index_name.append(row[2].value) #URL
        index_name.append(row[3].value) #人数
        index_name.append(row[5].value) #レシピ名と材料が一緒になった列 

        index_name_lists.append(index_name)

#index.材料.量が一緒になったリストを作る
index_ing_lists=[]
def create_index_inglist():   
    
    for row in ing_ws.iter_rows(min_row =2, min_col=1, max_col=3):
        index_ing =[]
        index_ing.append(row[0].value) #index列
        index_ing.append(row[1].value) #材料
        index_ing.append(row[2].value) #量
        index_ing_lists.append(index_ing)

# 検索文字が正しく入力されているか判定する
def input_word():  
    word = str(input("検索ワードを日本語で入力してください : "))
    word_result =  word.isalpha() #ひらがな/カタカナ/漢字が文字判定(True)される。数字は除外(False)
    if word_result :
        search_word(word)
    else:
        print("日本語以外の文字が入力されました  ")     
        input_word()  
    
#検索文字が一致するセルの座標をrecipe_indexファイルから検索
def search_word(word):    
    title_list = [] #検索件数を把握するためにtitle_list にtitle格納する
    for index_name in index_name_lists: 
         # 検索ワードと一致した時        
        if word in index_name[4]:
          
            # index と URLを取得する
            index = index_name[0]
            title = index_name[1]
            url = index_name[2]
            people_n = index_name[3]
            title_list.append(title)

            message(index, title, url, people_n)

            for index_ing in index_ing_lists:   #リストとして持っておく
                if str(index) in str(index_ing[0]):
                    ingredient = index_ing[1]
                    amount =  index_ing[2]           
                    print("{"+ str(ingredient)+""+str(amount)+"}")

    print( str( len(title_list))+ "件のレシピが見つかりました。" )

    if len(title_list) == 0: # 検索結果無い場合、検索ワード入力に戻る
        print("検索ワードの文字表記を変えると、検索結果が変わるかもしれません") 
        input_word()
    
    else: # 検索結果がある場合、レシピのindex選択に進む
        input_index()

def message(index, title, url, people_n):
    print("+++++++++++++++++++++++++++++++++++++++++")
    print("index : "+ str(index))
    print("レシピ名 : "+ title)
    print(str(people_n)+ " 人分のレシピです")
    print("URL : "+ url)
    
index_list =[] # レシピindexのリスト    
def input_index(): # 買い物リストに入れるレシピの index が 正しい数字か判定
    recipe_index = input("買い物リストに入れるレシピの indexを入力してください") 
    index_result = recipe_index.isdigit() # 正の整数か判定
    
    if index_result:
        if 0 <= int(recipe_index) <= 2031:
            index_list.append(int(recipe_index))
            end()        
        else:
            print("indexにない数字が入力されました") 
            input_index()
    else:
        print("数字以外の文字が入力されました") 
        input_index()

def end(): # レシピ検索継続するか 終了するか入力する関数
    input_n = input("まだレシピ検索しますか?Yes:1,No:0で選択してください") 
    n_result = input_n.isdigit() # 整数か判定
    if n_result:
        
        if int(input_n) == 1:
            input_word()
        
        elif int(input_n) == 0:
            print("レシピ選択を終わります。 現在" + str(len(index_list)) + "個のレシピが選択されています。")
            print("選択されたレシピ index : " + str(index_list))
            print(word_list[8]) #それでは買い物リストを作りましょう
        else:
            print("1 or 0で選択してください") 
            end()
    else:
        print("数字以外が入力されました") 
        end()

以上でレシピ検索システム編終了です。
次回は最終回、量の計算編です!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?