Нейросеть для раскрутки собачьего аккаунта в Инстаграм или робопёс в действии

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Механика

Скрипт для раскрутки назовём для краткости "робопёс". Представим, что этот скрипт от лица собачьего аккаунта периодически собирает посты по хэштегам на собачьи темы и ставит лайки таким постам. Какая-то часть авторов этих постов заинтресуется, кто им поставил лайк, и зайдёт на страницу собачьего аккаунта. Ну а дальше, как пойдёт. Кто-то пролистает пару экранов вниз и пойдёт дальше. Кто-то поставит робопсу пару ответных лайков (что тоже неплохо, лайки увеличивают охват постов). А если аккаунт понравится (что не исключено, ибо пёс весьма харизматичен), может и подписаться.

Осторожно: "масслайкинг"

Надо отметить, что такие действия называются "масслайкинг" и не особо привествуются Instagram. При появлении подозрительной робопёсей активности Instagram сначал вынесет несколько предупреждений, а потом может и навечно забанить аккаунт. Кстати, под запрет попадает и ручной масслайкинг (т.е. если лайкает не автоматизированный сервис, а лично Вы).

Есть мнение, что масслайкинг сейчас не особо работает. Ну что же, заодно и проверим.

Сервисы и библиотеки для масслайкинга и массфоловинга

Несмотря всё вышеизложенное, живут и процветают десятки различных сервисов для масслайкинга и массфоловинга (интересуюшиеся могут посмотреть здесь, здесь или погуглить самостоятельно). Это намекает на то, что масслайкинг всётаки работает.

Получается, как с сексом. Вроде все занимаются, но обсуждать в приличном обществе не принято. Опять же в интернетах можно найти эмпирически установленные ограничения для масслайкинга. Если робопёс не будет их превышать, то в бан его отправить не должны. Для молодых (менее полугода от даты регистрации) аккаунтов это не более 30 лайков в час или 720 в день.

Для питонистов есть специальные библиотеки. Наиболее известная - Instapy (12 тыс. звезд на Github, на минуточку). Есть менее известные. Кстати, недавно на Хабре была статья в которой разбирается очень даже достойная библиотека instabot. Но использовать их "в лоб" для автойлакинга по хэштегам лично я бы не стал. По нижеследующей причине.

Что не так с хэштегами

Проблема с высокачастотными хэштегами состоит в том, что они сильно зашумлены разным спамом (с которым Instagram тоже борется, но явно не особо успешно).

Вы видите пса, собаку или собачку? А они есть...
Вы видите пса, собаку или собачку? А они есть...

Коммерческие аккаунты или просто пользователи, которые хотят максимально раскрутиться, добавляют высокочастотные хэшеги к любым своим постам. И это, к сожалению, общепринятая практика.

Робопёс не хочет лайкать что не попадя, а готов дарить лайки исключтельно лайкам (и всем прочим породам собак), но никак не домам! А значит нужны какие-то дополнительные инструменты для отсеивания ненужного контента.

Анализ фото постов с помощью нейросети

По идее "левые" фотки к постам можно отсечь с помощью анализа изображений нейросетью. То есть робопёс должен скачивать картинку поста, и определять, есть на ней собака. Если есть - лайкать, если нет - пропускать. Такая задача называется Object Detection, для её решения есть специальные инструменты, а именно SSD детекторы.

На заглавной картинке к посту - пара собачьих фото, по которым прошелся SSD детектор на основе MobileNet v.2, обученный на датасэте COCO2017. Робопёс будет использовать архитектуру MobileNet, поскольку она мало весит и быстро работает и на обычной машине без GPU с приемлемой точностью. Кстати, на обоих фото собака определена нейросетью с вероятностью 94%.

Для желающих самостоятельно потестить, как работает SSD на произвольном посте выкладываю здесь кусок кода на python. Для удобства выложил скрипт на Github, но файл с весами не влез, придётся скачивать отдельно, в репозиории есть инструкция.

Код
import cv2
import json
from datetime import datetime
import requests
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

def id_class_name(class_id, classes):
    for key, value in classes.items():
        if class_id == key:
            return value

# Здесь вбиваем нужный пост
shortcode = 'CJ.........'

classNames = {}

with open('models/coco2017_labels.txt', 'r+', encoding='utf-8') as file:

    for line in file:
        key = int(line.split(':')[0])
        value = line.split(':')[1]
        classNames[key] = value.strip()
        
COLORS = np.random.uniform(0, 255, size=(len(classNames), 3))

s = requests.session()
r = s.get(f'https://www.instagram.com/p/{shortcode}/?__a=1', headers = {'User-agent': 'bot'})
url = r.json()['graphql']['shortcode_media']['display_resources'][0]['src']

resp = requests.get(url, stream=True)
image = np.asarray(bytearray(resp.content), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
image_height, image_width, _ = image.shape

frame_resized = cv2.resize(image,(300,300))
model = cv2.dnn.readNetFromTensorflow('models/frozen_inference_graphод.pb',
                                      'models/ssd_mobilenet_v2_coco_2018_03_29.pbtxt')
model.setInput(cv2.dnn.blobFromImage(frame_resized, size=(300, 300), swapRB=True))

output = model.forward()
detections = output[0, 0, :, :]
detections = detections[detections[:,2].argsort()]

for detection in detections:

    confidence = detection[2]
    class_id = int(detection[1])
    class_name = id_class_name(class_id, classNames)

    if (confidence > 0.3):

        box_x =      int(detection[3] * image_width)
        box_y =      int(detection[4] * image_height)
        box_width =  int(detection[5] * image_width)
        box_height = int(detection[6] * image_height)

        cv2.rectangle(image, (box_x, box_y), (box_width, box_height), COLORS[class_id], thickness=2)

        label = class_name + ": " + str(round(confidence, 2))
        labelSize, baseLine = cv2.getTextSize(label, cv2.FONT_HERSHEY_DUPLEX, 0.5, 1)
        yLeftBottom_ = max(box_y, labelSize[1])

        cv2.rectangle(image, (box_x, box_y + labelSize[1]), (box_x + labelSize[0], box_y), COLORS[class_id], cv2.FILLED)
        cv2.putText(image, label, (box_x, box_y + labelSize[1] - baseLine//2), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255))

plt.figure(figsize=(8,8))
plt.axis("off")
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
# Если хотите сохранить файл с обнаруженными классами в виде файла - раскомментируйте строку ниже
#plt.savefig(f'{shortcode}.png')

Для запуска ещё потребуется установить библиотеку OpenCV и несколько других. Все они импортируются в начале скрипта, если чего-то не будет хватать, доставьте через pip или conda install.

Для скачивания информации о посте используется запрос вида /?__a=1 к OpenAPI Instagram. Пока этот запрос работает без авторизации, но инста каждый день чего-нибудь да закручивает, так что наверное, скоро и его закроют. Больше о структуре данных, которую использует Instagram, можно опять же почерпнуть здесь.

Надо сказать, что собаки данной реализацией нейросети определяются корректно не всегда. Вот например:

Почему собаки не летают как птицы?
Почему собаки не летают как птицы?

Дело в том, что ракурс на фото выбран довольно необычный - нос собаки похож на клюв какой-то птицы вроде тукана. То есть в реальных условиях часть годного контента будет неминуемо отбракована, робопёс будет лайкать не всех собак. Но в рамках решаемой задачи с этим вполне можно смириться.

Продолжение следует. В ближайшее время разверну робопса на локальной машине поавтолайкаю и пособираю статистику по отклику на лайки.

Источник: https://habr.com/ru/post/537714/


Интересные статьи

Интересные статьи

Если честно, к Д7 у меня несколько неоднозначное отношение. В некоторых местах я попискиваю от восторга, а в некоторых хочется топать ногами и ругаться неприличными словами.
В статье описаны необходимые параметры сервера для оптимальной работы сайта на платформе 1С-Битрикс.
Заголовок статьи может показаться странным и это неспроста — он прекрасен именно тем, что написал его не я, а LSTM-нейросеть (а точнее его часть перед "или"). (схема LSTM взята из Understandin...
Водопад курильщика и водопад здорового человека Все мы знаем, как нарисовать сову. Нужно сначала нарисовать овал, потом еще окружность, ну а потом — получается шикарная сова. Конечно, это шу...
Одной из «киллер-фич» 12й версии Битрикса была объявлена возможность отдавать статические файлы из CDN, тем самым увеличивая скорость работы сайта. Попробуем оценить практический выигрыш от использова...