[GO] [Python] J'ai créé un système pour introduire "la recette que je veux vraiment" depuis le site de recettes!

introduction

Bonjour, c'est HanBei.

L'article précédent portait sur la collecte de données pour l'apprentissage automatique, mais nous continuerons cette fois.

Continuez à utiliser Google Colaboratory.

Si vous êtes intéressé, veuillez ** commenter ** ou ** LGTM **!

1-1. Objectif

J'utilise le site de recettes, mais ** "C'est beaucoup" **, ** "Le plat vraiment recommandé est-il délicieux? (Excusez-moi)" **, donc je vais trouver la recette que je veux.

1-2. Cible (raison de lire cet article)

** J'espère que cela sera utile pour ceux qui souhaitent obtenir des données pour l'apprentissage automatique en utilisant les données sur le Web **.

1-3. Attention

Le grattage est un ** crime ** si vous ne suivez pas correctement l'utilisation et le dosage.

"Je veux faire du grattage, alors ne t'inquiète pas!" Pour ceux qui sont optimistes ou inquiets, nous vous recommandons de lire au moins les deux articles ci-dessous.

miyabisun: "Ne posez pas de questions sur le site Q&R pour savoir comment gratter" nezuq: "Liste des précautions pour le scraping Web"

1-4. Éléments à vérifier

Cet article vous apprend à gratter, mais ** nous déclinons toute responsabilité **.

Pensez par vous-même et utilisez-le avec la bonne éthique.

2. Préparation

2-1. Examen du site de recettes

Cookpad, Nadia, White Rice.com Il existe un site de recettes pour, mais cette fois, nous utiliserons ** Rakuten Recipe **.

Raison, ・ Il existe des données quantitatives telles que «Je veux répéter», «C'était facile» et «J'ai sauvé». ・ De nombreuses recettes

est.

2-2. Rendre Google Colaboratory disponible

Si vous n'avez pas créé de compte Google pour utiliser Google Colaboratory, créez-en un.

Comment créer un nouveau bloc-notes ...

  1. Cliquez sur Google Colaboratory pour commencer.
  2. Créez-en un nouveau depuis Google Drive Référence: shoji9x9 "Résumé de l'utilisation de Google Colab"

3. Pratique

De là, j'écrirai le contenu de l'implémentation.

3-1. Introduction

Tout d'abord, importez la bibliothèque.

from bs4 import BeautifulSoup
from google.colab import drive
from google.colab import files
import urllib
import urllib.parse
import urllib.request as req
import csv
import random
import pandas as pd
import numpy as np
import time
import datetime

Décidez du nom du plat que vous souhaitez rechercher!

#Le nom du plat que vous souhaitez rechercher
food_name = 'curry'

3-2. Obtenez l'URL de la recette

Créez une fonction pour obtenir l'URL de la recette.

#Stocker l'url de chaque recette
recipe_url_lists = []

def GetRecipeURL(url):
  res = req.urlopen(url)
  soup = BeautifulSoup(res, 'html.parser')

  #Sélectionnez une gamme de liste de recettes
  recipe_text = str(soup.find_all('li', class_= 'clearfix'))
  #Divisez le texte acquis ligne par ligne et enregistrez-le dans la liste
  recipe_text_list = recipe_text.split('\n')

  #Lisez la liste ligne par ligne et extrayez uniquement les lignes qui correspondent au nom du plat
  for text in recipe_text_list:
    #Obtenez l'URL de chaque recette
    if 'a href="/recipe/' in text:
      #Spécifiez une pièce spécifique et mettez-la dans l'url
      recipe_url_id = text[16:27]
      #Combiner l'URL
      recipe_url_list = 'https://recipe.rakuten.co.jp/recipe/' + recipe_url_id + '/?l-id=recipe_list_detail_recipe'
      #URL du magasin
      recipe_url_lists.append(recipe_url_list)  

    #Obtenez le titre de chaque recette
    if 'h3' in text:
      print(text + ", " + recipe_url_list)

Vérifiez les recettes par ordre de popularité

#Nombre de pages que vous souhaitez rechercher
page_count = 2

#Encoder pour mettre le nom du plat dans l'URL
name_quote = urllib.parse.quote(food_name)

#Combiner les URL (une seule URL de page)
#Par ordre de popularité
base_url = 'https://recipe.rakuten.co.jp/search/' + name_quote
#Nouvelle commande d'arrivée
# base_url = 'https://recipe.rakuten.co.jp/search/' + name_quote + '/?s=0&v=0&t=2'

for num in range(page_count):
  #Pour obtenir après une page spécifique
  # num = num + 50

  if num == 1:
    #Combiner les URL (une seule URL de page)
   GetRecipeURL(base_url)

  if num  > 1:
    #Combiner les URL (URL à partir de la page 2)
    #Par ordre de popularité
    base_url_other =  'https://recipe.rakuten.co.jp/search/' + name_quote + '/' + str(num) + '/?s=4&v=0&t=2'
    #Nouvelle commande d'arrivée
    # base_url_other =  'https://recipe.rakuten.co.jp/search/' + name_quote + '/' + str(num) + '/?s=0&v=0&t=2'
    GetRecipeURL(base_url_other)

  #Appliquer la règle 1 seconde pour le scraping
  time.sleep(1)

Après cela, le titre et l'URL de la recette seront affichés. Searching_of_Delicious_Food_ipynb_Colaboratory.png

Vérifions le nombre de recettes obtenues ici!


#Nombre de recettes acquises
len(recipe_url_lists)

Une fois exécuté, 17 éléments sont affichés.

Ensuite, nous allons acquérir les données nécessaires à partir de chaque recette.


data_count = []
recipe_data_set = []

def SearchRecipeInfo(url, tag, id_name):
  res = req.urlopen(url)
  soup = BeautifulSoup(res, 'html.parser')

  for all_text in soup.find_all(tag, id= id_name):
    # ID
    for text in all_text.find_all('p', class_= 'rcpId'):
      recipe_id = text.get_text()[7:17]
      
    #date de sortie
    for text in all_text.find_all('p', class_= 'openDate'):
      recipe_date = text.get_text()[4:14]

    #c'était délicieux,C'était facile,J'ai pu enregistrer 3 types de timbres
    for text in all_text.find_all('div', class_= 'stampHead'):
      for tag in text.find_all('span', class_= 'stampCount'):
        data_count.append(tag.get_text())

    #J'ai fait le nombre de rapports
    for text in all_text.find_all('div', class_= 'recipeRepoBox'):
      for tag in text.find_all('h2'):
        #Lorsque le nombre de rapports est de 0
        if tag.find('span') == None:
          report = str(0)
        else:
          for el in tag.find('span'):
            report = el.replace('\n							', '').replace('Cas', '')

  print("ID: " + recipe_id + ", DATE: " + recipe_date + ",Numéro fait: " + report + 
        ",Je veux répéter: " + data_count[0] +
        ",C'était facile: " + data_count[1] +
        ",J'ai pu sauver: " + data_count[2]+
        ", url: " + url)

  #Stocker pour écrire dans un fichier csv
  recipe_data_set.append([recipe_id, recipe_date, data_count[0], data_count[1], data_count[2], report, url])

  #Vider le tableau contenant le nombre de tampons
  data_count.clear()

  #Restrictions de grattage
  time.sleep(1)

Ici, vérifiez les données acquises.


for num in range(len(recipe_url_lists)):
  SearchRecipeInfo(recipe_url_lists[num], 'div', 'detailContents')

Lorsque vous l'exécutez, vous pouvez voir qu'il a été acquis correctement. Searching_of_Delicious_Food_ipynb_Colaboratory (1).png

3-3. Exporter le fichier csv sur Google Drive

Créez une feuille de calcul sur Google Drive et exportez les données

#Montez le répertoire que vous souhaitez utiliser
drive.mount('/content/drive')

Sélectionnez n'importe quel dossier dans Google Drive et spécifiez le nom du fichier Veuillez préciser "○○○".

#Créez un dossier sur Google Drive et spécifiez la destination d'enregistrement
save_dir = "./drive/My Drive/Colab Notebooks/〇〇〇/"
#Sélectionnez un nom de fichier
data_name = '〇〇〇.csv'
#Enregistrer le fichier csv dans le dossier
data_dir = save_dir + data_name

#Ajouter un élément au fichier csv
with open(data_dir, 'w', newline='') as file:
  writer = csv.writer(file, lineterminator='\n')
  writer.writerow(['ID','Release Date','Repeat','Easy','Economy','Report','URL'])

  for num in range(len(recipe_url_lists)):
    writer.writerow(recipe_data_set[num])

#Enregistrez le fichier créé
with open(data_dir, 'r') as file:
  sheet_info = file.read()

Lorsqu'il est exécuté, 〇〇〇.csv sera affiché dans le répertoire spécifié. Veuillez vous référer au contenu jusqu'à présent dans une simple diapositive.

2020_05_22_レシピ検索_Google_スライド.png 2020_05_22_レシピ検索_Google_スライド (1).png

3-4. Pondération des données de recette

Vérifiez la sortie du fichier csv par Pandas.


#Charger csv
rakuten_recipes = pd.read_csv(data_dir, encoding="UTF-8")

#Prêt à ajouter à la colonne
df = pd.DataFrame(rakuten_recipes)

df

L'image de sortie est omise.

Ensuite, calculez le nombre de jours écoulés entre la date de publication de la recette et aujourd'hui.


# rakuten_recipes.Extraire la date de sortie de csv
date = np.array(rakuten_recipes['Release Date'])
#Obtenez la date actuelle
today = datetime.date.today()

#Faites correspondre le moule
df['Release Date'] = pd.to_datetime(df['Release Date'], format='%Y-%m-%d')
today = pd.to_datetime(today, format='%Y-%m-%d')

df['Elapsed Days'] = today - df['Release Date']

#Je ne retirerai que la valeur du nombre de jours écoulés
for num in range(len(df['Elapsed Days'])):
  df['Elapsed Days'][num] = df['Elapsed Days'][num].days

#Ne cochez que 5 lignes du haut
df.head()

Ensuite, le nombre de jours écoulés apparaîtra à côté de la colonne URL.

Ensuite, laissez le nombre de jours écoulés être ** poids ** et pesez les trois types de timbres: répétition, facile et économique. Ajoutez les données pondérées à la colonne de recette existante.

2020_05_22_レシピ検索_Google_スライド (2).png


#Fixé pour ne pas être trop petit
weighting = 1000000

#Extraire 3 types de tampons et rapporter les valeurs
repeat_stamp = np.array(rakuten_recipes['Repeat'])
easy_stamp = np.array(rakuten_recipes['Easy'])
economy_stamp = np.array(rakuten_recipes['Economy'])
report_stamp = np.array(rakuten_recipes['Report'])

#Total de chaque timbre et rapport
repeat_stamp_sum = sum(repeat_stamp)
easy_stamp_sum = sum(easy_stamp)
economy_stamp_sum = sum(economy_stamp)
report_stamp_sum = sum(report_stamp)

#Ajout d'une colonne de valeurs pondérées
'''
Répéter la pondération= (Nombre de tampons répétés ÷ répétition totale) × (Valeur corrigée ÷ nombre de jours écoulés depuis la date de publication)
'''
df['Repeat WT'] = (df['Repeat'] / repeat_stamp_sum) * (weighting / df['Elapsed Days'])
df['Easy WT'] = (df['Easy'] / easy_stamp_sum) * (weighting / df['Elapsed Days'])
df['Economy WT'] = (df['Economy'] / economy_stamp_sum) * (weighting / df['Elapsed Days'])

#Importance du rapport (plage de 0 à 1)
proportions_rate = 0.5

#Ajout d'une colonne de valeurs pondérées
'''
Répéter la pondération= (Répéter la pondération× (1 -importance)) × ((Nombre de rapports ÷ nombre total de rapports) ×importance[%])
'''
df['Repeat WT'] = (df['Repeat WT'] * (1 - proportions_rate)) * ((df['Report'] / report_stamp_sum) * proportions_rate)
df['Easy WT'] = (df['Easy WT'] * (1 - proportions_rate)) * ((df['Easy WT'] / report_stamp_sum) * proportions_rate)
df['Economy WT'] = (df['Economy WT'] * (1 - proportions_rate)) * ((df['Economy WT'] / report_stamp_sum) * proportions_rate)

À propos de la pondération ... Concernant le nombre de jours écoulés, supposons qu'il y ait des articles il y a un mois et il y a un an, et les mêmes 100 timbres sont attachés. Lequel est le plus recommandé pour la recette il y a un mois. Par conséquent, le score est inférieur pour les articles qui ont dépassé le nombre de jours.

Modifiez la plage des valeurs maximum et minimum des valeurs pondérées de 0 à 1. Je publierai la page que j'ai utilisée comme référence.

QUANON: "Convertir un nombre d'une plage en un nombre d'une autre plage"


df['Repeat WT'] = (df['Repeat WT'] - np.min(df['Repeat WT'])) / (np.max(df['Repeat WT']) - np.min(df['Repeat WT']))
df['Easy WT'] = (df['Easy WT'] - np.min(df['Easy WT'])) / (np.max(df['Easy WT']) - np.min(df['Easy WT']))
df['Economy WT'] = (df['Economy WT'] - np.min(df['Economy WT'])) / (np.max(df['Economy WT']) - np.min(df['Economy WT']))

df.head()

C'est le résultat de l'exécution. En faisant df.head (), seules les 5 premières lignes seront affichées. Searching_of_Delicious_Food_ipynb_Colaboratory (2).png

3-5. Afficher les recettes recommandées

Le score obtenu par l'utilisateur est évalué sur une échelle de 5 points et la recherche est effectuée.


#Utilisé pour spécifier la plage (1: 0-0.2, 2: 0.2-0.4, 3: 0.4-0.6, 4: 0.6-0.8, 5: 0.8-1)
condition_num = 0.2

def PlugInScore(repeat, easy, economy):
  #Argument dans la plage spécifiée
  if 1 >= repeat:
    repeat = 1
  if 5 <=repeat:
    repeat = 5
  if 1 >= easy:
    easy = 1
  if 5 <= easy:
    easy = 5
  if 1 >= economy:
    economy = 1
  if 5 <= economy:
    economy = 5

  #Affinez les recettes à partir de 3 types de partitions
  df_result =  df[((repeat*condition_num) - condition_num <= df['Repeat WT']) & (repeat*condition_num >= df['Repeat WT']) &
                  ((easy*condition_num) - condition_num <= df['Easy WT']) & (easy*condition_num >= df['Easy WT']) &
                  ((economy*condition_num) - condition_num <= df['Economy WT']) & (economy*condition_num >= df['Economy WT'])]
  # print(df_result)

  CsvOutput(df_result)

Exportez les résultats de la recherche dans un fichier csv. Veuillez saisir un nom pour 〇〇〇!


#Sélectionnez un nom de fichier
data_name = '〇〇〇_result.csv'
#Enregistrer le fichier csv dans le dossier
data_dir_result = save_dir + data_name

#Sortie csv
def CsvOutput(df_result):
  #Afficher le résultat réduit dans un fichier csv
  with open(data_dir_result, 'w', newline='') as file:
    writer = csv.writer(file, lineterminator='\n')
    #Titre
    writer.writerow(df_result)
    #Chaque valeur
    for num in range(len(df_result)):
      writer.writerow(df_result.values[num])

  #Enregistrez le fichier créé
  with open(data_dir, 'r') as file:
    sheet_info = file.read()
  
  AdviceRecipe()

Déclare une fonction pour afficher le résultat.


def AdviceRecipe():
  #Charger csv
  rakuten_recipes_result = pd.read_csv(data_dir_result, encoding="UTF-8")

  #Prêt à ajouter à la colonne
  df_recipes_res = pd.DataFrame(rakuten_recipes_result)

  print(df_recipes_res)

  print("Recommandé pour vous" + food_name + " 」")
  print("Entry No.1: " + df_recipes_res['URL'][random.randint(0, len(df_recipes_res))])
  print("Entry No.2: " + df_recipes_res['URL'][random.randint(0, len(df_recipes_res))])
  print("Entry No.3: " + df_recipes_res['URL'][random.randint(0, len(df_recipes_res))])

Enfin, attribuez une note à la recette que vous souhaitez réaliser et affichez les recommandations.


'''

plug_in_score(repeat, easy, economy)Remplacer
  
  repeat :Voulez-vous recommencer?
  easy   :Est-ce facile à faire?
  economy:Pouvez-vous économiser de l'argent et le gagner?

Évaluez la subjectivité en 5 étapes de 1 à 5 et remplacez-la par un entier.

1 est négatif, 5 est la position

'''

PlugInScore(1,1,1)

3 types de points ** 1 **: Voulez-vous recommencer? ** 1 **: Est-ce facile à faire? ** 1 **: Pouvez-vous économiser de l'argent?

Le résultat de l'exécution est ... Searching_of_Delicious_Food_ipynb_Colaboratory (3).png

4. Problèmes / problèmes

・ Examen de la méthode d'évaluation Les trois valeurs pondérées sont tirées par la recette la plus élevée, ce qui donne des résultats extrêmes. Par conséquent, il est biaisé sur 1 ou 5.

・ Il y a peu d'articles estampillés Environ ** 10 **% des recettes ont des tampons et des rapports, et environ ** 90 **% de tous les 0 Par conséquent, il peut être absurde d'évaluer la recette par points. Il devrait y avoir une excellente recette dans All 0.

5. Examen

J'ai utilisé ce système pour rechercher "kimchi de porc" et j'ai essayé de le préparer. C'était délicieux car c'était une recette recommandée ^^

C'était intéressant car j'ai pu découvrir la recette qui était enterrée.

Merci à tous ceux qui ont lu jusqu'ici. Je vous serais reconnaissant de bien vouloir nous faire part de vos commentaires et conseils ^^

Recommended Posts

[Python] J'ai créé un système pour introduire "la recette que je veux vraiment" depuis le site de recettes!
Je veux démarrer beaucoup de processus à partir de python
Je souhaite envoyer un message de Python à LINE Bot
Je veux créer un système pour éviter d'oublier de serrer la clé 1
Je veux utiliser jar de python
Je veux créer un environnement Python
Je souhaite envoyer un signal uniquement du sous-thread au thread principal
[Mémo Python] Je souhaite obtenir un nombre hexadécimal à 2 chiffres à partir d'un nombre décimal
J'ai fait un programme pour vérifier la taille d'un fichier avec Python
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
J'ai créé une fonction pour voir le mouvement d'un tableau à deux dimensions (Python)
Je veux créer une fenêtre avec Python
Je souhaite envoyer un e-mail depuis Gmail en utilisant Python.
[Python] Je veux gérer 7DaysToDie depuis Discord! 1/3
Je veux faire un jeu avec Python
Je veux utiliser le solveur ceres de python
[Python] Je veux gérer 7DaysToDie depuis Discord! 2/3
Je veux créer du code C ++ à partir de code Python!
Je veux écrire dans un fichier avec Python
Je veux afficher la progression en Python!
[LINE Messaging API] Je souhaite envoyer un message du programme à tout le monde LINE
J'ai créé une bibliothèque pour faire fonctionner la pile AWS CloudFormation à partir de CUI (Python Fabric)
J'ai créé un outil pour générer du Markdown à partir du fichier JSON Scrapbox exporté
[Python] J'ai essayé d'obtenir le nom du type sous forme de chaîne de caractères à partir de la fonction type
J'ai fait un script pour enregistrer la fenêtre active en utilisant win32gui de Python
Je souhaite intégrer une variable dans une chaîne Python
Je veux répéter plusieurs fois un générateur Python
Je veux générer rapidement UUID (memo memo) ~ Edition Python ~
Je veux écrire en Python! (2) Écrivons un test
J'ai créé un module Python pour traduire les commentaires
Je voulais utiliser la bibliothèque Python de MATLAB
Je veux échantillonner au hasard un fichier avec Python
Je veux hériter de l'arrière avec la classe de données python
Je veux travailler avec un robot en python.
[Python] Je veux faire d'une liste imbriquée un taple
Je veux écrire en Python! (3) Utiliser des simulacres
J'ai fait une commande pour marquer le clip de la table
J'ai créé une bibliothèque python qui fait rouler le rang
Je veux utiliser le jeu de données R avec python
Je veux faire fonctionner un ordinateur quantique avec Python
Je veux dire aux gens qui souhaitent importer depuis un répertoire supérieur avec Python direnv
Je souhaite prendre une capture d'écran du site sur Docker en utilisant n'importe quelle police
J'ai fait un texte Python
maya Python Je veux réparer à nouveau l'animation cuite.
J'ai créé un package pour filtrer les séries chronologiques avec python
[Python] Je souhaite obtenir un ensemble commun entre numpy
J'ai créé un outil pour créer un nuage de mots à partir de wikipedia
J'ai fait une fonction pour vérifier le modèle de DCGAN
Je souhaite calculer le temps d'arrêt autorisé à partir du taux de fonctionnement
[Python] Je souhaite utiliser l'option -h avec argparse
Je veux installer le package de requirements.txt avec poésie
Je veux connaître la nature de Python et pip
J'ai essayé de changer le script python de 2.7.11 à 3.6.0 sur Windows10
Je veux ajouter un joli complément à input () en python
Je vous ai fait exécuter des commandes depuis un navigateur WEB
Je veux créer un Dockerfile pour le moment.
Extraire la valeur la plus proche d'une valeur à partir d'un élément de liste en Python
J'ai créé une classe pour obtenir le résultat de l'analyse par MeCab dans ndarray avec python
J'ai créé un serveur avec socket Python et ssl et j'ai essayé d'y accéder depuis le navigateur