Где поесть? Куда сходить? Ищем ответ на вопрос с помощью пары рекомендаций и скрипта Python - LEFT JOIN

Свяжитесь с нами в любой удобной для вас форме

Менеджер

Написать в телеграмм

Онлайн
Телеграмм
или
Заполните форму

3 минут чтения

*

22 марта 2022 г.

Где поесть? Куда сходить? Ищем ответ на вопрос с помощью пары рекомендаций и скрипта Python

Поскольку наш блог придерживается технологий, аналитики и IT-тематики, то обсуждение политики мы здесь, естественно опустим. Однако, сложно не заметить, что многие сейчас целенаправленно или волей случая оказываются в незнакомых городах и странах. Или планируют переезд, или просто путешествуют. В любом случае, где бы вы ни оказались, всегда хочется выстроить быт, сходить на завтрак или выпить вкусный кофе. Если вам интересно, чем в этих вопросах может помочь наш скрипт и проверить его в действии – продолжайте читать.

Что мы придумали?

Итак, предположим, что вы оказались в незнакомом городе. У вас есть несколько рекомендаций от друзей или просто несколько проверенных мест, где вам вкусно и красиво.
Наш алгоритм может быстро увеличить этот список в несколько раз, дополнив его 5-10 рекомендациями того же качества или уровня. Звучит здорово, да?

Как мы это реализовали?

Мы все еще не умеем колдовать, поэтому решили прибегнуть к более простому способу — написать Python-скрипт для решения этой задачи.
Начинаем, как всегда, с подготовки. Самая важная шестеренка в нашем скрипте – Instagram API (деятельность социальной сети признана экстремистской и запрещена в Российской Федерации).


from instagrapi import Client
import time
import pandas as pd

Затем, подключаемся к API, чтобы приступить к обработке данных.


cl = Client()
cl.login(«username», «password»)

Наша задача реализуется двумя небольшими скриптами. Первый собирает и обрабатывает геометки из Instagram (деятельность этой социальной сети признана экстремистской и запрещена в Российской Федерации), а также находит людей, которые отмечали эти геометки на фотографиях. Мы знаем, что эти места наверняка нравятся не только нам и предполагаем, что мы нашли тех людей, которые разделяют наши вкусы и ценности. Поэтому, мы собираем все недавние геометки в их профиле и так получаем список рекомендаций. Затем, с помощью второго скрипта мы узнаем точные адреса этих мест в Яндекс.Картах, чтобы определиться с выбором.

Сбор и обработка данных

Начинаем работу. Для того чтобы получить список рекомендаций нам нужны три подходящих примера, например кофейни Санкт-Петербурга: Смена, ТЧК, Civil. Наш скрипт принимает на вход идентификаторы геоточек заведений.

Как их получить?
1. Переходим по ссылке в профиль заведения, например:
https://www.instagram.com/smenacafe/
2. Анализируем геометки в постах (считаем, что официальный профиль содержит правильные геометки)
3. Находим ссылку на геометку, например:
https://www.instagram.com/explore/locations/727911037416015/smenacafe/
4. Цифры в ссылке и есть идентификатор геоточки
727911037416015

После того как мы нашли геометки первичных рекомендаций, нам нужно найти тех пользователей, кто ходит в это заведение (= отмечает его на своих фотографиях). Для этого мы берем последние 150 отметок заведения.
Конечно, это должны быть реальные пользователи, а не бизнес-аккаунты, потому что там могут присутствовать рекламные интеграции, а мы в них не заинтересованы.


pk_place_ids = [541835746291313, 2103750586526340, 100059475]
 
print(‘Getting users started’)
 
# получаем пользователей, которые отметили заведение на фото
users = []
for i in pk_place_ids:
    # получаем 150 последних постов с выбранной геометкой
    medias = cl.location_medias_recent(i, amount=150)
    
    for m in medias:
        user_id = m.dict()[‘user’][‘pk’]
        if not user_id in users:
            users.append(user_id)
    
count_users = len(users)
 
print(f’Getting {count_users} users finished’)
 
print(‘Getting not business users started’)
 
# отбираем тех пользователей, чьи аккаунты не являются комерческими
users_not_business = []
for u in users:
    try:        
        u_info = cl.user_info(u).dict()
        
        if not u_info[‘is_business’]:
            users_not_business.append(u)
    except:
        next
 
count_nb_users = len(users_not_business)
 
print(f’Getting {count_nb_users} not business users finished’)
 
print(‘Getting location started’)

Мы нашли людей, которые отмечали эти места у себя в профиле. Теперь мы собираем все места, которые отмечены в профилях этих людей и выводим эти места списком, сортируя по числу упоминаний.


# получаем места, которые посетил пользователь
locations = {}
 
end_cursor = None
for u in users_not_business:
    # скрипт работает довольно медленно, поэтому анализируем только 100 последних постов пользователя
    # посты получаем порциями 20 раз по 5 с сохранением курсора
    for page in range(20):
        u_medias, end_cursor = cl.user_medias_paginated(u, 5, end_cursor=end_cursor)
        for m in u_medias:
            # обернул в обработку исключений, т.к. иногда парсер падает
            try:
                # задержка для снижения чатсоты запросов в инстаграм
                time.sleep(1)
                # по идентификатору поста получаем данные поста (важно, что есть имя места, но нет его координат)
                info = cl.media_info(m.dict()[‘pk’]).dict()
                if ‘location’ in info:               
                    loc_key = info[‘location’][‘pk’]
                    
                    # вывод имени отмеченного места (для лога)
                    #print(info[‘location’][‘name’])
                    
                    # если место встретилось первый раз, то узнаем его координаты
                    if loc_key not in locations:
                        
                        # для того, чтобы узнать координаты, берем последний пост с такой геометкой
                        loc_data = cl.location_medias_recent(loc_key, amount=1)[0].dict()
                        
                        lng=»
                        lat=»
                        
                        if ‘location’ in loc_data:
                            lng=loc_data[‘location’][‘lng’]
                            lat=loc_data[‘location’][‘lat’]
                        
                        locations[info[‘location’][‘pk’]] = [info[‘location’][‘name’],1,lng,lat] 
                    else:
                        locations[info[‘location’][‘pk’]][1] = locations[info[‘location’][‘pk’]][1] + 1
                    
                    # сохраняем результат в csv файл
                    ids = [i for i in locations]
                    names = [locations[i][0] for i in locations]
                    vizits = [locations[i][1] for i in locations]
                    lngs = [locations[i][2] for i in locations]
                    lats = [locations[i][3] for i in locations]
 
                    df = pd.DataFrame(
                        {‘id’: ids,
                        ‘name’: names,
                        ‘vizit’: vizits,     
                        ‘lng’: lngs,
                        ‘lat’: lats     
                        })
 
                    df.sort_values(‘vizit’, ascending=False).to_csv(‘places.csv’, index=False)                  
                    
            except:
                next
                
count_locations = len(locations)
 
print(f’Getting {count_locations} location finished’)

Второй скрипт должен находить координаты новых рекомендаций в Яндекс.Картах.


# получим категории из справочника организаций сервиса Яндекс.Карты
import requests
 
# ключ API можно найти в кабинете разработчика
api_key = «—»
 
addrs = []
urls = []
cat1s = []
cat2s = []
cat3s = []
 
df = pd.read_csv(«places.csv»)
 
for i, row in df.iterrows():
    
    time.sleep(1)
    
    lng = row[‘lng’]
    lat = row[‘lat’]
    name = row[‘name’]
    print(name)
        
    req = f»https://search-maps.yandex.ru/v1/?text={name}&results=1&type=biz&lang=ru_RU&ll={lng},{lat}&spn=0.01,0.01&apikey={api_key}»
 
    response = requests.get(req)
 
    addr = »
    url = »
    cat1 = »
    cat2 = »
    cat3 = »
 
    if response.status_code == 200:
        # обернули в обработку исключений, т.к. иногда падает
        try:
            company_data = response.json()[‘features’][0][‘properties’][‘CompanyMetaData’]
                        
            addr = company_data[‘address’]
            url = company_data[‘url’]
            
            count_categories = len(company_data[‘Categories’])
            
            # у организации может быть до 3 категорий, сохраняем их все
            if count_categories > 0:
                if count_categories == 1:
                    cat1 = company_data[‘Categories’][0][‘name’]
                elif count_categories == 2:
                    cat1 = company_data[‘Categories’][0][‘name’]
                    cat2 = company_data[‘Categories’][1][‘name’]
                elif count_categories == 3:
                    cat1 = company_data[‘Categories’][0][‘name’]
                    cat2 = company_data[‘Categories’][1][‘name’]
                    cat3 = company_data[‘Categories’][2][‘name’]             
            
        except:
            pass
        
    addrs.append(addr)
    urls.append(url)
    cat1s.append(cat1)
    cat2s.append(cat2)
    cat3s.append(cat3)
    
df[‘address’] = addrs
df[‘url’] = urls
df[‘cat1’] = cat1s
df[‘cat2’] = cat2s
df[‘cat3’] = cat3s
df.to_csv(‘places_24.csv’, index=False)

Результаты

Выпить кофе в Петербурге

Мы решили проверить, как работает скрипт на примере трех наших любимых кофеен в Петербурге. Получилось следующее:

Поужинать в Петербурге

Также мы протестировали наш скрипт, задав три рекомендации классных ресторанов Питера: Chang, Tiger Lilly, Jack and Chan.

Ограничения скрипта

1. Скрипт сбора данных работает недостаточно быстро (примерно 100 геоточек в час).

2. У геоточек может быть несколько дублей. Бывают геоточки с одинаковыми названиями, но отличающимися по координатам. Если честно, то по сути в геоточках просто хаос. Поэтому остается много ручной работы на этапе обработки и получения результатов.

3. Яндекс отдает данные хорошо: база организаций очень большая, но для большинства объектов заполнена не одна, а целых три категории. У кафе может быть первая категория бар, затем кафе, затем ресторан. В общем, приходится опять же проверять многое вручную.

4. Сделать единую процедуру пока не очень получается.

Пока со скриптом можно работать в два этапа:

– Первый этап – получение данных из инстаграма (название, частота посещений, координаты) и затем полуавтоматическая чистка от ненужных объектов + объединение дублей (это важно, так как бесплатная квота Яндекс.Карт – 500 запросов в день),

– Второй этап – получение из Яндекс.Карт категорий, адреса, сайта и затем ручная сверка категорий и выбор наиболее точной категории из трех.

576 просмотров

Добавить комментарий

[ Рекомендации ]

Читайте также

[ Дальше ]