この記事は以下の続きです
今回は、楽天レシピカテゴリ一覧API と 楽天レシピカテゴリ別ランキングAPIを使って
集めたレシピから検索 ➡ 買い物リストに入れたいレシピを選択する
という機能を作っていきます!
このように、検索ワードを入力したら、以下の検索結果が出てきます。
この中から、以下の様に indexを選択します。
さらに再度レシピ検索を行うか選択する ところまでを作ります。
買い物リスト作成アプリの概要はこちら
目次
項番 | ページ内リンク |
---|---|
1 | レシピ検索機能を作るのに必要な手順 |
2 | 準備 |
3 | 検索ワードの入力 |
4 | 検索ワードがヒットするレシピを見つけて表示 |
5 | indexを選択する |
6 | レシピ検索を継続するか問う関数をつくる |
7 | 全コード |
レシピ検索機能を作るのに必要な手順
- ユーザが検索ワードを入力
- 検索ワードが「レシピ名」「レシピの材料」から当てはまるレシピをピックアップ
- ピックアップしたレシピの「レシピ名」「レシピindex」「何人分のレシピか」「URL」をそれぞれ表示
- 何件レシピがヒットしたか表示
- 買い物リストに入れたいレシピのindexを選択
- 検索を続けるか選択する
この手順を踏んでいきます。
準備
検索ワードを、こちらのレシピ一覧のB列の「レシピ名」とE列の「レシピ材料」から探すのですが、2列分検索しなくてはいけなくなります。
検索時間を短くしたいので、F列にレシピ名とレシピ材料の列を合体させた列を作り、1列検索すれば良いようにします。
さらにこのあと、ヒットしたレシピの「レシピindex」や「何人分のレシピか」の情報を得たいので、この表自体をリストとして取得しておきます。
列を合体
#必要ライブラリのインポート
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列に 「レシピ名」+「レシピ材料」の列が新たにできました。
表をリストとして取得する
#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重配列のリストになります。
同じようにこちらの「材料と量」のExcelもリスト化しておきます。index_ing_listsと名前を付けます。
検索ワードの入力
検索ワードはinput関数を使ってユーザーに入力してもらいます。
word = str(input("検索ワードを日本語で入力してください : "))
次に、isalphaメソッド
を使って入力した文字が日本語であるかを判定します。
isalphaメソッド
は主に指定したワードが英語で構成されている場合、Trueで返しますが、ひらがな・カタカナ・漢字で構成されていてもTrueを返します。
これを利用します。
参考文献
[解決!Python]文字列が英字(文字)のみで構成されているかどうかを判定するには(isalpha/isasciiメソッド、re.match/re.fullmatch関数)
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,何人分,レシピ名+材料が格納されたリスト
から探します。
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))+ "件のレシピが見つかりました。" )
次に、検索結果がある時、ない時の条件分岐を作ります。
検索結果があれば、次の動作へ
検索結果がなければ、再度検索ワード入力へ戻るようにします。
条件分岐を入れて、関数化するとこちら
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関数を使って選択してもらいます。
recipe_index = input("買い物リストに入れるレシピの indexを入力してください")
また、このindexが正の整数であるか?
indexに無い数字を入力していないか?判定するために条件分岐を加えます。
正の整数であるかは、indigistメソッド
で判定します。
isdigit メソッドは文字列中のすべての文字が数字であり、かつ 1 文字以上ある場合に、Trueを返します。
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選択に戻るように条件分岐を追加します。
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メソッド
を使って入力された文字が整数か判断します。
input_n = input(word_list[6]) #まだレシピ検索しますか?Yes:1,No:0
n_result = input_n.isdigit() # 整数か判定
入力された文字が整数である場合、レシピ検索を続けるか、終了するかで条件分岐を作ります。
さらに、関数化すると以下
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()
全コード
#必要ライブラリのインポート
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()
以上でレシピ検索システム編終了です。
次回は最終回、量の計算編です!