Что делать, если Instagram не дал доступ к API? Дополнение

    Здравствуйте ещё раз! Я прочёл её и мне показалось, что её можно продолжить.

    image

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

    1. Самые полезные функции (постинг и удаление постов) доступны только из мобильного приложения Instagram, эмуляция запросов сложна, так как надо вытащить из приложения ключ, который с каждой новой версией обновляется.
    2. Web-версия обрезана, но радует, что в ней есть возможность лайкать, комментировать и удалять комментарии
    3. Есть API, но процедура его получения удручающе долгая и спамерам и ботам такой путь точно не светит. Плюс было много моментов, когда соглашения в API менялись, что не всегда удобно.

    Хоть я и связался с Instagram не для того, чтобы сделать очередного спам-бота, который может подписываться и лайкать, но возиться с получением Instagram API мне ну очень не хотелось, поэтому пришлось написать собственную библиотеку для взаимодействия с Instagram.

    Хочется сказать, что работать с Web-версией Instagram очень даже приятно по двум причинам:

    1. О любой страничке можно получить краткую информацию, если отправить GET запрос вида:

    https://instagram.com/zuck/?__a=1

    И ответом является JSON с доступной информацией, первыми 10 постами странички и прочим. Очень приятно.

    2. Если же краткой информации не хватает, то тут есть ещё одна приятная новость. Дозагрузить фоточки, подписки, комментарии можно со помощью определённого запроса вида

    https://www.instagram.com/graphql/query/?query_id=17888483320059182&variables=...

    , где в variables передаются переменные для обработки в формате JSON. Ответом также является JSON. Да и вообще, очевидно, что работает это всё на GraphQL, так что чтобы понять, как обрабатываются запросы, можно даже погуглить.

    На основе данных знаний и построена вся библиотека. Я вкратце опишу, как её можно использовать, может, кому-то пригодится. Кстати, я там в репозитории указал лицензию BSD 3. Подскажите, может, мне стоит её поменять, чтобы не было никаких трудностей?

    Установка


    Устанавливать её не надо. Точнее, мне было лень прописывать всякие setup.py или упаковывать, когда библиотека состоит всего из одного файла. Поэтому там просто файл instagram.py, который подключается так:

    import instaparser

    Как ей пользоваться?


    Взаимодействие с Instagram возможно либо с авторизацией, либо без. Без авторизации отсутствуют функции просмотра подписок и подписчиков, и, очевидно, невозможно что-то лайкнуть, что-то откомментировать и так далее. Единственные ограничения с авторизацией: это невозможно выкладывать посты и удалять их.

    Приведу пример взаимодействия без авторизации:

    
    from instaparser.agents import Agent
    from instaparser.entities import Account 
    
    agent=Agent()
    account=Account("zuck")
    
    agent.update(account)
    
    media=agent.get_media(account, count=100)
    for m in media:
        print(m)
    

    Как вы поняли, данный скрипт прогружает информацию о странице Марка Цукерберга, загружает последние 100 постов с его странице и выводит их на экран.

    Хочу сказать, что если бы я не написал

    agent.update(account)

    то выполнить загрузку постов не получилось бы, так как никакой информации о странице Цукерберга известно не было.

    А вот пример с авторизацией:

    
    from instaparser.agents import AgentAccount
    from instaparser.entities import Account
    
    agent=AgentAccount("oleg_yurchik", "imasuperpassword")
    agent.update()
    account=Account("zuck")
    agent.update(account)
    # and etc.
    

    Это, так называемый Hello, world!. Или быстрый старт.

    А теперь расскажу подробнее:

    Instagram, на самом деле, имеет всего 6 сущностей:

    1. Аккаунт
    2. Пост
    3. Геолокация
    4. Комментарий
    5. Хэштег
    6. Сторис

    Всё остальное — это просто списки этих сущностей, такие как лайки, подписки, подписчики и прочее. И для каждой сущности есть свой класс. Для аккаунтов — Account, постов — Media, геолокаций — Location, комментариев — Comment, хэштегов — Tag, историй — Story. И каждый из них (кроме комментариев) нужно обновить, прежде чем работать с ним. То есть если хочется загрузить все свои посты, пролайкать их и получить список геолокаций, то нужно выполнить следующее:

    
    from instaparser.agents import AgentAccoun
    
    agent=AgentAccount('oleg.yurchik', 'anothersuperpassword')
    agent.update()
    media=agent.get_media(count=agent.media_count)
    locations=[]
    for m in media:
        agent.like(m)
        agent.update(m)
        if m.location:
            locations.append(m.location)
    

    А если позже надо получить последние 10 постов по определённой геолокации, то надо будет сделать следующее:

    
    agent.update(location)
    media=agent.get_media(location, count=10)
    

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

    Библиотека основана на библиотеке requests, и одной из фишек я считаю то, что в методы также можно передать дополнительные параметры для requests. Такая идея пришла ко мне, когда я первый раз получил 429 ошибку от Instagram. Нужно было использовать прокси.

    Например, можно сделать так:

    
    media=agent.get_media(count=agent.media_count, settings={'proxies': {'https': '127.0.0.1:80'}})
    

    где 127.0.0.1:80 — можно указать свой прокси

    Также ещё одной фишкой, я думаю, может являться перехват ошибок.

    В классах Agent и AgentAccount (те, что и производят общение с Instagram) есть словарь, организованный как дерево, он называется exception_actions. В нём в виде ключей хранятся классы исключений, а в виде значений — функции. Если вдруг произошла какая-то ошибка, она перехватывается и выполняется функция из словаря. Этой функции передаётся объект исключения и параметры, с которыми выполнялся запрос. Она может выполнить какое-то действие и вернуть изменённые (или нет) параметры запроса. Выполнение запроса повторится снова. И будет повторятся столько раз, сколько указано в параметре Agent.repeats. По умолчанию стоит 1.

    А ещё можно не беспокоиться о переполнении памяти.

    У класса каждой сущности есть словарь, в котором хранятся все объекты данного класса (или объекты подкласса даже). Таким образом, если Вы случайно создадите, например, аккаунт, который уже был создан, конструктор вернёт вам ссылку на ранее созданный аккаунт.

    Если вы случайно пропустили ссылку на репозиторий в тексте, то вот она ещё раз.

    И напоследок скажу, что из-за некоторых решений появились и некоторые проблемы:

    1. Например, проблема при повторном создании объекта. Если вдруг вы захотите использовать аккаунт как рабочий и взаимодействовать через него, а он уже ранее был создан как обычный аккаунт, то создать его снова не получиться. Пока я не знаю, как это решить.
    2. Перехват ошибок иногда ведёт себя очень странно и не до конца протестирован.

    Я очень надеюсь, что, может быть, данное решение кому-нибудь пригодится, надеюсь на любые полезные комментарии и на помощь в допиливании этой штуки. В указанной мною статье был приведён пример такого скрипта на PHP, но он занимался только сбором информации и, по-моему, он работал только со старой версией веб-нитерфейса Instagram.

    Спасибо за внимание.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 40

      0
      А получив это API доступ к Instagram, rtmp случайно не появляется для стриминга?
        0
        Я не знаю, я ещё года 2 назад пытался получить доступ к API, но мне не дали) Его, как мне рассказывали, дают в приоритете каким-либо веб-приложениям, и чаще всего уже запущенным
          0
          если еще не нашли — rtmp можно получить без доступа к апи
          +1
          Очень жаль, что не все методы работают (например, получение лайков и комментариев без авторизации). Насколько мне известно, query_id привязывается к сессии, а вы их вынесли в качестве магических констант.
            0
            Насколько мне известно, query_id привязывается к сессии, а вы их вынесли в качестве магических констант.

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

            Нет, без авторизации точно можно получать комментарии, а лайки, если честно, не пробовал. Но если web-интерфейс позволяет, то и в приложении можно.
            +1
            Если кому интересно, делал как-то телегам бот для масс фолловинга t.me/instanode_bot
            Использовал приватное api instagram, в итоге имея базу прогоняю по ним аккаунты
            Проект на github github.com/hazratgs/instalator-telegram
              +3
              2 года назад написал плагин, который публикует товары в инстаграм
              www.webasyst.ru/store/plugin/shop/instagram
              Он эмулирует телефон.
              Как работал ключ, так и работает до сих пор.
                0
                Он маскируется под старую версию приложения? Я думал, они закрывают доступ)
                  +2
                  Могу дать доступ в репо на гитлаб, если в личку скинешь мыло. Посмотришь класс, который генерит клиента. Я его делал на основе другого класса, который нашел на гитхабе.
                0
                Бегло посмотрел код, как я понимаю список новостей авторизованного пользователя получить нельзя?
                  0

                  Пока нет, но в теории можно)

                    0
                    Наверно возьмусь как время высвободится. Давно хочу ленту из инстаграма отправить в rss читалку.
                  –1
                  когда библиотека состоит всего из одного файла

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

                      756 строк — это не много
                      А вот делать много файлов с каким-то специальным библиотечным оформлением, когда можно сделать один, встраиваемый под видом части своего исходника — уже наоборот "много".

                      0

                      А у инстаграма есть ограничения по запросам? И как это обходите? Например у вк 3 запроса в секунду, и нормально парсить только если сбор распределять на разные аккаунты.

                        0
                        Как я выше писал, все запросы делаются на основе библиотеки requests. Если использовать парсинг с авторизацией, то прокси не поможет, это да. Мне приходилось вставлять обработчик ошибок, чтобы при 429 он ожидал какое-то время
                          0

                          А сам инстаграм не даёт никаких цифр запросы в секунду? И по опыту можете, пожалуйста, сказать сколько нужно времени (вместе с ожиданием) что бы скачать например 10000 постов?

                            0

                            Официально у них описано только API, и там тоже не ахти. В варианте веб версии некоторую инфу можно вытаскивать анонимно, а с API это невозможно. Если про реальные цифры, то чтобы не уйти в 429 я пробовал ставить ожидание после каждого запроса от 1 до 2 секунд. С 1 секундой он уходит в 429 ошибку, с 2 — никогда. Думаю, при таком варианте — это где-то 40-50 запросов в минуту. Так как максимум можно вытащить около 1000 запросов за раз (скорее всего, есть цифра точная, но я не ставил экспериментов пока), то на 10000 постов надо будет потратить около 3-4 часов. Это если быть авторизованным. А если вытаскивать посты без авторизации с использованием прокси — то ограничений нет. Опять же, если бы мобильное приложение или API давали лучшие результаты(

                              0

                              1000 постов за запрос*

                                0

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

                                  0

                                  Спасибо. Да я имел ввиду картинка, текст, теги и т.д.

                                    0
                                    На самом деле, технически можно достать и за полминуты. По-моему, из запросов типа ?__a=1 можно достать ещё маленькие изображения и, кажется, текст. Но это не точно
                                      0

                                      Хм… интересно, спасибо. Как перейду к инсте надо будет видимо исследовать этот вопрос.

                                  0
                                  Читайте
                                  Если кратко — 2 часа (если Ваше приложение Instagram заапрувил). Это не считая комментариев к постам, т.к. они выкачиваются отдельными запросами, а значит требуют дополнительных лимитов.
                                    0
                                    И кстати там используется довольно интересная штука с time-sliding limits, т.е. кол-во запросов в час считается не относительно некоторого времени (например с 11.00 до 12.00) а за час назад отсчитывая от текущего момента
                                      0

                                      Спасибо, да полезный линк.

                              0
                              вот кстати интересный скрипт для накрутки, github.com/timgrossmann/InstaPy слелан с использованиям Selenium
                                0
                                Для класса который знает о своих экземплярах хорошо бы взять weakref.WeakSet. Тогда не нужно будет писать кастомный __del__, и когда на экземпляр не будет ссылок тогда из WeakSet он пропадёт автоматически. Да и в целом код станет немного проще.
                                  0
                                  Ни для кого не секрет, что самая популярная и прибыльная площадка для рекламы, бизнеса и прочего — Instagram.

                                  Сильное заявление

                                  Рекомендую библиотеку, которая эмулирует поведение android-приложения и позволяет делать почти всё (сейчас живые трансляции не доступны), что возможно в приложении https://github.com/mgp25/Instagram-API/.

                                  Если вам нужен только постинг, используйте мой докер-контейнер (https://github.com/zhuharev/instagram-rest-api), который запускается как микро-сервис и позволяет (пока только) постить фото и галлереи просто rest-запросом.
                                    0
                                    Может кто подскажет такое же, но только для ноды?
                                      0
                                      Вообще все проекты гуглятся по запросу «instagram unofficial api»

                                      Есть адаптация для ноды https://github.com/huttarichard/instagram-private-api и для питона https://github.com/danleyb2/Instagram-API

                                      Лучше использовать оригинальную библиотеку, потому что у неё бОльшее комьюнити и библиотеку часто обновляют.
                                        0
                                        А она, как я понял, также эмулирует приложение, да? И в нём надо обязательно авторизовываться?
                                          0
                                          Она шлёт такие же запросы, как и приложение. Да, работа с библиотекой доступна только по логину и паролю.
                                      0
                                      Библиотека хорошая.
                                      Единственный минус конечно это то что нужно следить за ключём приложения (так как в один прекрасный момент, без обновления скрипта и ключа — всё накроется).
                                      На сколько я понял лёгкого способа изымать ключ приложения — нет.

                                      Ну и ещё сейчас они ввели политику — «платите, или ничего не спрашивайте».
                                      +2

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

                                        0
                                        Да, есть такое. Это тоже можно обойти, но из-за того, что эта проблема встречается редко — я не смог её решить(
                                          +1
                                          нужно авторизироваться на своём компьютере, например, (что бы ip был такой же, как и ip где вы авторизировались с мобильного), а потом просто скопировать cookies на удалённый сервер
                                        0
                                        спасибо за библиотеку, буквально то что я искала для личных нужд уже долгое время.
                                        Для своей цели доработала получение линку на видеофайл если контент является видео.
                                        if self.is_video:
                                        self.video_url = data['video_url']
                                        в методе Media.__setDataFromJSON__(..)
                                          0
                                          Очень рад, что она приносит пользу) Если есть какие-то изменения, то не могли бы Вы форкнуть репозиторий и предложить изменения?

                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                        Самое читаемое