Pull to refresh

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

PythonМашинное обучениеКонтент-маркетингИскусственный интеллектСоциальные сети и сообщества

Механика

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

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

Надо отметить, что такие действия называются "масслайкинг" и не особо привествуются 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, можно опять же почерпнуть здесь.

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

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

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

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

Tags:pythonнейросетиinstagramopencvsmm
Hubs: Python Машинное обучение Контент-маркетинг Искусственный интеллект Социальные сети и сообщества
Total votes 16: ↑13 and ↓3 +10
Views6.3K

Popular right now