Comparación del surtido de platos de tres restaurantes en San Petersburgo.

Nunca antes había tenido que lidiar con el análisis de datos de Internet. Por lo general, todos los datos para el trabajo (analista de datos) provienen de las descargas de la empresa utilizando una interfaz interna simple, o están formados por consultas sql a tablas directamente desde el almacenamiento, si necesita algo más complejo que "mirar los ingresos de la anterior mes". 





Por lo tanto, quería dominar alguna herramienta simple para analizar páginas html con el fin de poder recopilar datos de Internet usando código en un IDE conveniente sin involucrar herramientas de terceros. 





Los sitios para la recopilación de datos se seleccionaron según el principio "no hay bloqueador del analizador sintáctico" y "puede resultar algo interesante del análisis de estos datos". Por lo tanto, la elección recayó en una variedad de platos para la entrega de tres restaurantes en San Petersburgo: "Ciudad de Tokio", "Eurasia" y "2 Berega". Tienen aproximadamente el mismo enfoque de cocina y una variedad similar, por lo que claramente hay algo para comparar. 





Compartiré el analizador en sí para uno de los restaurantes.





import requests
from bs4 import BeautifulSoup
import pandas as pd
import datetime

print("   : " + str(datetime.datetime.now()))
#     
urllist = ['https://www.tokyo-city.ru/spisok-product/goryachie-blyuda1.html',
           'https://www.tokyo-city.ru/spisok-product/sushi.html',
           'https://www.tokyo-city.ru/spisok-product/rolly.html',
           'https://www.tokyo-city.ru/spisok-product/nabory.html',
           'https://www.tokyo-city.ru/spisok-product/new_lunches.html',
           'https://www.tokyo-city.ru/spisok-product/pitctca.html',
           'https://www.tokyo-city.ru/spisok-product/salaty.html',
           'https://www.tokyo-city.ru/spisok-product/-supy-.html',
           'https://www.tokyo-city.ru/spisok-product/goryachie-zakuski1.html',
           'https://www.tokyo-city.ru/spisok-product/wok.html',
           'https://www.tokyo-city.ru/spisok-product/pasta.html',
           'https://www.tokyo-city.ru/spisok-product/gamburgery-i-shaverma.html',
           'https://www.tokyo-city.ru/spisok-product/Tokio-FIT.html',
           'https://www.tokyo-city.ru/spisok-product/deserty.html',
           'https://www.tokyo-city.ru/spisok-product/childrensmenu.html',
           'https://www.tokyo-city.ru/spisok-product/napitki1.html',
           'https://www.tokyo-city.ru/new/',
           'https://www.tokyo-city.ru/spisok-product/postnoe-menyu.html',
           'https://www.tokyo-city.ru/hit/',
           'https://www.tokyo-city.ru/vegetarian/',
           'https://www.tokyo-city.ru/hot/',
           'https://www.tokyo-city.ru/offers/',
           'https://www.tokyo-city.ru/spisok-product/sauces.html',
           'https://www.tokyo-city.ru/spisok-product/Pirogi-torty.html']
#      
names_all = []
descriptions_all = []
prices_all = []
categories_all = []
url_all = []
weight_all = []
nutr_all = []
# 
for url in urllist:
    response = requests.get(url).text
    soup = BeautifulSoup(response, features="html.parser")
    items = soup.find_all('a', class_='item__name')
    itemsURL = []
    n = 0
    for n, i in enumerate(items, start=n):
        itemnotfullURL = i.get('href')
        itemURL = 'https://www.tokyo-city.ru' + itemnotfullURL
        itemsURL.extend({itemURL})
        m = 0
        namesList = []
        descriptionsList = []
        pricesList = []
        weightList = []
        nutrList = []
        itemResponse = requests.get(itemURL).text
        itemsSoup = BeautifulSoup(itemResponse, features="html.parser")
        itemsInfo = itemsSoup.find_all('div', class_='item__full-info')
        for m, u in enumerate(itemsInfo, start=m):
            if (u.find('h1', class_='item__name') == None):
                itemName = 'No data'
            else:
                itemName = u.find('h1', class_='item__name').text.strip()
            if (u.find('p', class_='item__desc') == None):
                itemDescription = 'No data'
            else:
                itemDescription = u.find('p', class_='item__desc').text.strip()
            if (u.find('span', class_='item__price-value') == None):
                itemPrice = '0'
            else:
                itemPrice = u.find('span', class_='item__price-value').text
            if (u.find('div', class_='nutr-value') == None):
                itemNutr = 'No data'
            else:
                itemNutr = u.find('div', class_='nutr-value').text.strip()
            if (u.find('div', class_='item__weight') == None):
                itemWeight = '0'
            else:
                itemWeight = u.find('div', class_='item__weight').text.strip()
            namesList.extend({itemName})
            descriptionsList.extend({itemDescription})
            pricesList.extend({itemPrice})
            weightList.extend({itemWeight})
            nutrList.extend({itemNutr})
        df = pd.DataFrame((
            {'Name': namesList,
             'Description': descriptionsList,
             'Price': pricesList,
             'Weight': weightList,
             'NutrInfo': nutrList
             }))
        names_all.extend(df['Name'])
        descriptions_all.extend(df['Description'])
        prices_all.extend(df['Price'])
        weight_all.extend(df['Weight'])
        nutr_all.extend(df['NutrInfo'])
        df['Category'] = soup.find('div', class_='title__container').text.strip()
        categories_all.extend(df['Category'])
result = pd.DataFrame((
    {'Name': names_all,
     'Description': descriptions_all,
     'Price': prices_all,
     'Category': categories_all,
     'NutrInfo': nutr_all,
     'Weight': weight_all,
     }))
print("   : " + str(datetime.datetime.now()))
      
      



- / . , . , , , - - .





- .









, , , , , , . 





:





. , . , , , , . 





  • City





“ City” 19 5 , , (, ). - 351.









“” - 13 , 301 . , “ City” , 40% , , , “”. 





  • 2





- 241 15 .





, , , . 





№1: ?

, “” .





, , , . , “”, “ ”, “”, “”, “” “” + .





:





, “2 ” - №1 . , “” (“ City” - 20, “” - 17 “2 ” - 51).





  - , “” .





№2: ?

, - “”, “” “ ”. . , , “ ”, . 





100 , :





“2 ” , “ ”. , “ + ” . “ ” “ City” “”. 





“ City” . “2 ” 2 . “” . 100 “” 30% ( , ), “ City” . 





, :





“” . “” 30% . 





“2 ” , . , “ ” , , 2 + ( ). .





“ City” .





№3: ?

, , . , . 





“ City” 205 100 , . , . “2 ” 35% , . , , , . 





: ? 

, , , , .





A pesar del mayor contenido calórico por cada 100 gramos y una gran cantidad de comida rápida, “2 Shores” ofrece un menú bastante equilibrado, mientras que la misma “Ciudad de Tokio” tiene un claro sesgo hacia los carbohidratos. 





BZHU "Eurasia" es de alguna manera demasiado uniforme, prácticamente sin emisiones, por lo que despierta sospechas. 





En general, existen dudas sobre la exactitud de las conclusiones que hice en esta pregunta en particular; tal vez, para la respuesta correcta a la pregunta, estos indicadores deben evaluarse de alguna manera de manera diferente. 






Aquí hay una investigación tan pequeña, pero curiosa que, en mi opinión, surgió del pensamiento aleatorio de “analizar algo”.








All Articles