- PVSM.RU - https://www.pvsm.ru -
Некоторое время назад на Хабре была опубликована статья [1] про поиск похожих аккаунтов в Twitter'e. На комментарии автор, к сожалению, не реагировал, потому пришлось изобретать велосипед. Но чтобы не делать уж совсем то же самое, было решено искать похожие аккаунты в Instagram с помощью Google App Engine, да так, чтобы воспользоваться сервисом мог каждый. Так появился instalytics.ru [2]*.
Самое сложное, конечно же, оказалось в том, чтобы реализовать сервис для всех (ну, и остаться в пределах бесплатных квот Google App Engine и учесть ограничения Instagram API [3]).
Реализовано все следующим образом —
- name: followers-get
rate: 1/m # 1 task per minute
bucket_size: 1
max_concurrent_requests: 1
retry_parameters:
task_retry_limit: 2
min_backoff_seconds: 30
Каждая задача, в случае, если за один запрос были получены не все подписчики, создает новую задачу:
if users and users.get('pagination') and users.get('pagination').get('next_cursor'):
cursor = users.get('pagination').get('next_cursor')
url = '/task/followers-get?user_id='+user_id
url += '&cursor=' + cursor
taskqueue.add(queue_name='followers-get', url=url, method='GET')
- name: subscriptions-get
rate: 5000/h
При этом после выполнения каждого запроса, на всякий случай, спим по 0,72 секунды (=60*60/5000).
К сожалению, в бесплатной версии Google App Engine можно осуществить только 50'000 операций записей в базу данных в сутки. Т.к. каждая задача может создать новую задачу, то изначальный вариант — записывать результат выполнения каждой задачи в базу данных — пришлось заменить на новый — результат выполнения предыдущей задачи передается как параметр новой задачи, и лишь последняя задача записывает результат в базу:
if users and users.get('pagination') and users.get('pagination').get('next_cursor'):
cursor = users.get('pagination').get('next_cursor')
params = {
'user_id': user_id,
'f_user_id': f_user_id,
'cursor': cursor
}
if more_subscriptions:
params['subscriptions'] = ','.join(more_subscriptions)
taskqueue.add(queue_name='subscriptions-get', url='/task/subscriptions-get', params=params, method='POST')
Некоторые пользователи (такие, как @instagram [4], например) имеют миллионы подписчиков. Дабы не тратить драгоценные ресурсы на получение всех их подписчиков, задача завершается после получения 100'000 подписчиков.
memcache.set('subscriptions'+str(user_id), ','.join(str(x) for x in followers), 1209600)
Данные из memcache могут быть удалены в любой момент. Чтобы избежать ситуации с «зависшим» запросом (когда все задачи по запросу были выполнены, но memcache был удален и мы об этом, соответственно, не знаем), раз в несколько часов запускается задача, которая проверяет нет ли запросов, получивших статус получения подписчиков более чем 2 недели назад (пока считается, что это то время, за которое точно будут завершены все задачи). Если такие запросы находятся, то они «силой» переводятся на следующий этап.
ctx = ndb.get_context()
ctx.set_cache_policy(lambda key: False)
ctx.set_memcache_policy(lambda key: False)
В результате многочисленных вычислений на этом этапе выбираются 300 наиболее популярных пользователей, на которых подписаны ваши пользователи.
Указанные выше подходы и оптимизации пока позволяют оставаться в рамках выделенных GAE бесплатных квот, хотя получение результата и занимает достаточно много времени. Нужна ваша помощь — добавляйте [2] своих пользователей в очередь, посмотрим сколько времени займет их анализ.
В будущем планирую добавить к сервису распознавание настоящих людей / компаний в Instagram, но без машинного обучения тут не обойтись — так что это будет отдельной задачей.
* Русский язык на сайте пока не работает — не могу разобраться [6], почему django translation не работает на GAE.
Автор: and7ey
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/110995
Ссылки в тексте:
[1] статья: http://habrahabr.ru/post/273531/
[2] instalytics.ru: http://instalytics.ru
[3] Instagram API: https://www.instagram.com/developer/
[4] @instagram: https://www.instagram.com/instagram/
[5] этого: http://instalytics.ru/result/ahFlfmluc3RhLWFuYWx5dGljc3IUCxIHUmVxdWVzdBiAgICAgICACgw
[6] не могу разобраться: http://stackoverflow.com/questions/34979813/how-to-use-django-translation-with-gae
[7] Источник: https://habrahabr.ru/post/276237/
Нажмите здесь для печати.