[PYTHON] Cartographiez et profitez des magasins ciblés pour la campagne GoToEat

introduction

J'étais intéressé par la campagne GoToEat parce qu'elle est devenue un sujet brûlant dans le marathon aristocratique des oiseaux. Cette fois, j'aimerais utiliser les techniques de grattage et de cartographie de Python pour cartographier les magasins ciblés pour la campagne. Site de la campagne GoToEat du ministère de l'Agriculture, des Forêts et de la Pêche

Données d'utilisation

Nous avons recueilli des informations en grattant la page de Magasins ciblés pour la campagne de journaux alimentaires.

En un coup d'œil, je n'ai pas trouvé le libellé selon lequel le grattage était interdit sur le site ...

Je vais omettre le code source du scraping cette fois et ne donnerai qu'un aperçu. Les informations à acquérir sont ['Nom du magasin', 'Genre', 'Taux de révision', 'Budget minimum', 'Numéro de téléphone', 'Informations sur le tabagisme', 'Adresse', 'Préfecture', 'Indicatif régional', 'URL ']ça ira.

tabelog.jpg


import requests
from bs4 import BeautifulSoup
import time
import pandas as pd
from pprint import pprint


def scrape_page(soup, df, cols):
    for title in soup.find_all('div', class_='list-rst__rst-name'):
        #Acquisition du nom du magasin
        name = title.find('a').text.strip()
        #Obtenir l'URL du magasin
        shop_url = title.find('a').get('href')
        #Obtenir le genre
        genre = title.find('span', class_='list-rst__area-genre cpy-area-genre').text
        genre = genre.replace('/', '').replace(' ', '').replace('、', ',')

        print('「' + name + 'Est en cours d'acquisition ...')

        #Grattez la page de chaque boutique à partir de l'URL obtenue et obtenez des informations détaillées
        res_shop = requests.get(shop_url)
        soup_shop = BeautifulSoup(res_shop.content, 'html.parser')
        time.sleep(0.1)

        #Préfectures,Acquisition de zone
        prefecture = shop_url.split('/')[3]
        area = shop_url.split('/')[4]

        #Obtenez une adresse
        address = soup_shop.find('p', class_='rstinfo-table__address').text.strip()

        #Obtenez le taux de bouche à oreille--Puisqu'une erreur se produit, contrôlez-la avec une instruction try
        try:
            rate = float(soup_shop.find('span', class_='rdheader-rating__score-val-dtl').text.strip())
        except ValueError:
            rate = '-'
        #Obtenez le budget minimum
        budget = soup_shop.find('em', class_='gly-b-dinner').text.strip()
        budget = budget.split('~')[0].replace('¥', '').replace(',', '')
        budget = int(budget)

        #Obtenez le numéro de téléphone
        phone_num = soup_shop.find('p', class_='rstinfo-table__tel-num-wrap').text.strip()

        #Acquisition d'informations sur le tabagisme
        smoke = soup_shop.find('p', class_='p-input-form__line').text.strip()

        #Créez une liste vide pour chaque boutique et ajoutez
        shop_datas = []
        shop_datas.append(name)
        shop_datas.append(genre)
        shop_datas.append(rate)
        shop_datas.append(budget)
        shop_datas.append(phone_num)
        shop_datas.append(smoke)
        shop_datas.append(address)
        shop_datas.append(prefecture)
        shop_datas.append(area)
        shop_datas.append(shop_url)

        #Générer un bloc de données à partir d'une liste et fusionner
        df_shop = pd.DataFrame([shop_datas], columns=cols, index=None)
        df = pd.concat([df, df_shop], sort=False)

    return df


def job():
    url = 'https://tabelog.com/go-to-eat/list/?page='
    page_cnt = 1
    cols = ['name', 'genre', 'rate', 'budget', 'tel', 'smoke', 'address', 'prefectures', 'area', 'url']
    df = pd.DataFrame(columns=cols, index=None)
    url = url + str(page_cnt)
    res = requests.get(url)
    soup = BeautifulSoup(res.content, 'html.parser')

    df = scrape_page(soup, df, cols)

    pprint(df.columns.values)
    pprint(df.head().values)


job()

production

Obtention d'informations sur "Viande grillée au charbon de bois Hiyori" ...
Obtention d'informations sur "Viande grillée au charbon de bois / Cuisine coréenne KollaBo Ebisu store" ...
Obtention d'informations sur "Miraku" ...
Obtention d'informations sur "Wine Bar. Dipunto Shibuya Shinnan Store" ...
Obtenir des informations sur "La cuisson du steak de bœuf Kobe Grill au charbon de bois Yuzuki Hana" ...
Obtention d'informations sur "KARASUMA italien de l'Alberta de poissons et légumes" ...
Obtention d'informations sur le "Ningyocho Wine Bar" ...
Obtention d'informations sur "Basashi et Motsu Nabe Izakaya Kyushu Komachi Private Room All-you-can-drink Kanayama 2-chome" ...
Obtention d'informations sur "Adult Japanese Sake Bar Irori" ...
Obtention d'informations sur "Hidden Bunch Machida" ...
Obtention d'informations sur "Aloha Table Yokohama Bay Quarter" ...
Obtention d'informations sur "Beer Garden Terrace Iidabashi" ...
Obtention d'informations sur "l'Université Takkanmari" ...
Obtention d'informations sur "Private Room Steak & Italian Dining VT Ebisu" ...
Obtention d'informations sur "Yamakoya Sakaba Kemono" ...
Obtention d'informations sur "Genkatsugu" ...
Obtention d'informations sur le "Kyomachi Koi Shigure Shinjuku Main Building" ...
Obtention d'informations sur "GINTO Ikebukuro store" ...
Obtention d'informations sur "Satsuma Jidori et salle privée Izakaya Straw Fire Shinjuku" ...
"Grossiste en viande 25-Obtention d'informations sur "89" ...

array(['name', 'genre', 'rate', 'budget', 'tel', 'smoke', 'address',
       'prefectures', 'area', 'url'], dtype=object)
array([['Viande grillée au charbon de bois\u3000 Hiyori', 'Viande grillée,Taverne,steak', 3.2, 4000, '050-5869-1319',
        'Tous les sièges peuvent être fumés', '1 Nakayama Tedori, Chuo-ku, Kobe City, Préfecture de Hyogo-7-5 S Bâtiment 2F', 'hyogo', 'A2801',
        'https://tabelog.com/hyogo/A2801/A280101/28032248/'],
       ['Viande grillée au charbon de bois / Cuisine coréenne KollaBo Ebisu store', 'Viande grillée,Cuisine coréenne,Taverne', 3.09, 3000,
        '050-5571-4836', 'Tous les sièges sont non-fumeurs', '1 Ebisu Nishi, Shibuya-ku, Tokyo-14-1 bâtiment Sunrise\u30002F',
        'tokyo', 'A1303',
        'https://tabelog.com/tokyo/A1303/A130302/13178659/'],
       ['Miraku', 'Taverne,Fruits de mer et fruits de mer,Bol de riz garni de sashimi', 3.59, 3000, '050-5595-5384', 'Fumée séparée',
        '1 Kyomachi, Ogura Kita-ku, ville de Kitakyushu, préfecture de Fukuoka-6-28', 'fukuoka', 'A4004',
        'https://tabelog.com/fukuoka/A4004/A400401/40001071/'],
       ['Bar à vin. Magasin Dipunt Shibuya Shinnan', 'Bar Bar,Taverne,italien', 3.08, 2000,
        '050-5589-7383', 'Fumée séparée', '1 Shinnan, Shibuya-ku, Tokyo-20-17 B1F', 'tokyo', 'A1303',
        'https://tabelog.com/tokyo/A1303/A130301/13186934/'],
       ['Bifteck de bœuf Kobe cuisson grill au charbon de bois Yuzuki Hana', 'steak,Cuisine et petits plats,Viande grillée', 3.1, 10000,
        '050-5594-6576', 'Tous les sièges sont non-fumeurs', '4 Kano-cho, Chuo-ku, Kobe-shi, Hyogo-8-19 Bâtiment Parfum 2F',
        'hyogo', 'A2801',
        'https://tabelog.com/hyogo/A2801/A280101/28050226/']],
      dtype=object)

J'ai pu obtenir les informations sur une page avec succès. Après cela, si vous comptez la page du script comme ci-dessus et la bouclez pour chaque préfecture, vous pouvez obtenir toutes les informations (transpiration qui a pris beaucoup de temps).

Carte

J'ai utilisé le folium comme dans l'exemple, mais je ne peux pas mapper à moins que j'entre la latitude et la longitude en plus de l'adresse. J'ai cherché de diverses manières, mais en utilisant ce site, il est facile de passer d'une adresse à la latitude et à la longitude Je l'ai utilisé parce qu'il semblait que je pouvais l'obtenir. Si vous téléchargez un fichier csv avec l'adresse, vous pouvez télécharger le fichier avec la latitude et la longitude ajoutées à la colonne. Enregistrez-le sous tabelog_geo.csv et vérifiez le contenu des données.


df = pd.read_csv('tabelog_geo.csv', encoding='shift_jis')
print('Le nombre de données:{}'.format(len(df)))
print('-------column---------')
pprint(df.columns.values)
print('-------head values----')
pprint(df.head().values)

production

Le nombre de données:15020
-------column---------
array(['name', 'genre', 'rate', 'budget', 'tel', 'smoke', 'address',
       'url', 'prefectures', 'area', 'LocName', 'fX', 'fY', 'iConf',
       'iLvl'], dtype=object)
-------head values----
array([['Bar à viande de cheval rebondit Madamachi Mita', 'Bar Bar,Taverne,italien', 3.51, 3000, '050-5869-1861',
        'Tous les sièges sont non-fumeurs', '5 Shiba, Minato-ku, Tokyo-22-5 Bâtiment Harada 1F',
        'https://tabelog.com/tokyo/A1314/A131402/13143781/', 'tokyo',
        'A1314', 'Tokyo/Minato-ku/Shiba/5-chome/N ° 22', 139.74643999999998,
        35.648109999999996, 5.0, 7.0],
       ['Dorado', 'bistro,français,nourriture occidentale', 3.64, 5000, '050-5596-1243', 'Tous les sièges sont non-fumeurs',
        '3 Sakae, Naka-ku, ville de Nagoya, préfecture d'Aichi-10-14 Pivot Lion Building 2F',
        'https://tabelog.com/aichi/A2301/A230102/23029870/', 'aichi',
        'A2301', 'Préfecture d'Aichi/Ville de Nagoya/Naka-ku/Sannomaru/4-chome', 136.90649, 35.18425, 5.0, 6.0],
       ['Taverne Ryu no Su', 'Taverne,Fruits de mer et fruits de mer,Gyoza', 3.16, 3000, '050-5456-3379',
        'Tous les sièges sont non-fumeurs', '2 Yukimachi, Chitose-shi, Hokkaido-5-1',
        'https://tabelog.com/hokkaido/A0107/A010701/1024501/',
        'hokkaido', 'A0107', 'Hokkaido/Chitose City/Yukimachi/2-chome/Adresse 5', 141.64700000000002,
        42.822959999999995, 5.0, 7.0],
       ['Kushikatsu Dengana Yokohama Nanko', 'Taverne,Brochettes / brochettes frites,hormone', 3.01, 0, '050-5597-9448',
        '-', '2 Minamiyuki, Nishi-ku, Yokohama-shi, Kanagawa-8-20SFBuilding2F',
        'https://tabelog.com/kanagawa/A1401/A140101/14079956/',
        'kanagawa', 'A1401', 'Préfecture de Kanagawa/Nakagun/Ville de Ninomiya/Ninomiya', 139.25673999999998,
        35.30523, 5.0, 5.0],
       ['Viande grillée au charbon de bois / Cuisine coréenne Kolla Bo Shimbashi Store', 'Taverne,Viande grillée,Cuisine coréenne', 3.06, 3000,
        '050-5592-3837', 'Fumée séparée', '2 Shimbashi, Minato-ku, Tokyo-8-17 Bâtiment Sanken 1F',
        'https://tabelog.com/tokyo/A1301/A130103/13197832/', 'tokyo',
        'A1301', 'Tokyo/Minato-ku/Shimbashi/2-chome/N ° 8', 139.7563, 35.66747, 5.0, 7.0]],
      dtype=object)

O-chan et les colonnes fX, fY contiennent des informations de latitude et de longitude.

Graphique de données

Je me demandais comment les taux de journalisation des aliments sont distribués, je vais donc le tracer en utilisant seaborn. Un histogramme et un tracé de violon.

#Générer un histogramme
def plot_hist(df):
    #Parce que certains tarifs ne peuvent pas être obtenus et sont enregistrés comme 0
    df = df[df['rate'] != 0]
    sns.set()
    fig, ax = plt.subplots(figsize=(10, 6))
    sns.distplot(
        df['rate'], bins=10, color='blue', label='rate',
        kde=True)
    ax.set_title('histogram --tabelog rate')
    plt.show()

#Génération d'intrigue de violon
def plot_violin(df):
    df = df[df['rate'] != 0]
    sns.set()
    fig, ax = plt.subplots(figsize=(10, 6))
    sns.violinplot(x=df['rate'].values, color='lightgreen')
    ax.set_title('violin_plot --tabelog rate')
    plt.show()

histo_tabelog.png

violin_tabelog.png

Je n'ai jamais utilisé d'intrigue pour violon pour la première fois, mais je suis surpris que cela devienne involontairement obscène. En dehors de cela, on peut lire que les magasins avec une note d'environ 3,4 ou plus sont très bien notés dans l'ensemble.

Cartographie avec folium

Si vous cartographiez toutes les informations, ce sera un nombre énorme, alors je voudrais épingler les informations à l'avance sur la carte. Cette fois, "Italie" est incluse dans le genre, le budget maximum est de "10000 yens", le tarif journalier est de "3,2 ou plus" et les préfectures sont "Tokyo". De plus, dans le graphique précédent, un taux de 3,4 ou plus semble être bon, donc pour les magasins avec un taux de 3,4 ou plus, faites-le ressortir en vert.

import folium
import pandas as pd


def param_input(df):
    #Réglage de chaque paramètre-Non précisé''
    param_genre = 'Italie'  #entrée str
    param_budget = 10000  #budget maximum d'entrée int
    param_rate = 3.2  #débit le plus bas d'entrée flottante
    param_prefecture = 'tokyo'  #str Entrée alphabet demi-largeur
    param_address = ''  #entrée str

    #Affiner df en fonction du paramètre
    if param_genre != '':
        df = df[df['genre'].str.contains(param_genre)]
    if param_budget != '':
        df = df[df['budget'] <= param_budget]
    if param_rate != '':
        df = df[df['rate'] >= param_rate]
    if param_prefecture != '':
        df = df[df['prefectures'] == param_prefecture]
    if param_address != '':
        df = df[df['address'].str.contains(param_address)]

    return df


def make_folium_map(df):
    #Générer une carte avec le tout premier enregistrement comme point de départ
    start_loc = df[['fY', 'fX']].values[0]
    m = folium.Map(location=start_loc, tiles='Stamen Terrain', zoom_start=12)

    for data in df[['fY', 'fX', 'name', 'rate', 'budget', 'smoke']].values:
        lat = data[0]
        lon = data[1]
        name = data[2]
        rate = data[3]
        budget = data[4]
        smoke = data[5]

        #Générer un caractère ping
        ping_text = '{name}<br>{rate}<br>{budget}<br>{smoke}' \
            .format(name=name,
                    rate='Évaluation:' + str(rate),
                    budget=str(budget) + 'Yen ~',
                    smoke=smoke)

        #icône selon taux_définir la couleur
        # 3.Afficher 4 ou plus en vert
        if rate > 3.4:
            icon_color = 'green'
        else:
            icon_color = 'blue'

        #Mettez une épingle sur la carte
        folium.Marker([lat, lon],
                      tooltip=ping_text,
                      icon=folium.Icon(color=icon_color)).add_to(m)
        m.save('tabelog_map.html')

df = pd.read_csv('tabelog_geo.csv', encoding='shift_jis')
df = param_input(df)
make_folium_map(df)

résultat

tabelog.jpg

Si vous effectuez un zoom avant et déplacez le curseur, les informations du magasin s'affichent.

tabelog_zoom.jpg

J'ai pu mapper avec succès dans le fichier html. Ce serait encore mieux s'il pouvait être téléchargé sur le Web en utilisant heroku, mais comme il est actuellement en cours d'essai, il sera publié sous forme de capture d'écran rapide.

Il peut être intéressant de découvrir de nouvelles choses en générant des nombres aléatoires et en décidant au hasard dans quel magasin aller. Après tout, j'ai tendance à aller dans les magasins où je vais toujours.

prime

[Ce site](https://hikiniku11029.hatenablog.com/entry/2019/06/18/folium%E3%81%A7%E3%83%92%E3%83%BC%E3%83%88% E3% 83% 9E% E3% 83% 83% E3% 83% 97% E3% 81% AE% E4% BD% 9C% E3% 82% 8A% E6% 96% B9% E3% 82% 92% E3% 81% 8A% E3% 81% BC% E3% 81% 88% E3% 81% 9F) J'ai fait une carte thermique en référence. L'endroit où il y a un magasin haut de gamme brille fortement.

heat.jpg

heat_wide.jpg

Recommended Posts

Cartographiez et profitez des magasins ciblés pour la campagne GoToEat
Scraping du site officiel GoToEat de Shizuoka et liste des magasins ciblés pour la campagne Izu
Comparez la vitesse d'ajout et de carte Python