Instagram, одна из наиболее богатых данными публичных площадок в интернете, и вместе с тем одна из самых сложных для программного чтения. Профили и публикации рендерятся на стороне клиента с помощью JavaScript, платформа агрессивно выявляет автоматизированный трафик, а обычный HTTP-запрос к URL профиля обычно возвращает почти пустую оболочку. В этом руководстве показано, как парсить данные Instagram с помощью Python способом, который действительно работает, оставаясь строго в рамках публичных данных.

Сразу обозначим границы: всё здесь ограничено публичными данными из публичных аккаунтов. Это означает публичные поля профиля, публичные подписи к публикациям, публичное количество лайков и комментариев, а также публичные URL публикаций. Это не распространяется на закрытые аккаунты, контент за входом в систему, личные сообщения, списки подписчиков или персональные данные отдельных людей. Instagram и его материнская компания Meta ограничивают автоматический доступ в своих условиях использования, поэтому прочитайте раздел о легальности в конце, прежде чем применять это к реальным задачам. Для производственного или коммерческого использования официальный Instagram Graph API является правильным инструментом, а не скрапер.

Что вы создадите

Небольшой Python-скрипт, который принимает URL публичного профиля Instagram, загружает полностью отрендеренную страницу через Crawling API с JavaScript-токеном и извлекает несколько публичных полей:

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

Обратите внимание на то, что намеренно отсутствует: без списков подписчиков, без личностей комментаторов, без контента закрытых аккаунтов, без контактных данных. Это персональные данные отдельных людей, и их сбор здесь намеренно выходит за рамки.

Почему обычный запрос не работает в Instagram

Запросите URL публичного профиля Instagram с помощью обычного HTTP-клиента, и вы получите ответ, который технически успешен, но практически бесполезен. Тело представляет собой JavaScript-оболочку: реальный контент появляется только после того, как скрипты страницы выполняются в браузере и загружают данные из внутренних конечных точек. Помимо этого, Instagram быстро выявляет автоматизированный трафик. Диапазоны IP датацентров, отсутствие поведения браузера и повторяющиеся шаблоны запросов блокируются или ограничиваются задолго до загрузки интересующего контента.

Поэтому рабочему скраперу Instagram нужны сразу две вещи в одном запросе: реальный браузер, рендерящий страницу, и IP-адрес, который платформа воспринимает как обычного посетителя. Можно собрать это самостоятельно с помощью headless-браузера и пула ротируемых резидентных прокси, но поддержание такого стека в рабочем состоянии, это и есть основная работа. Crawling API объединяет оба компонента в одном вызове. Вы отправляете URL с JavaScript-токеном, API рендерит страницу за доверенным резидентным IP и возвращает готовый HTML для парсинга. Для более глубокого изучения темы обратитесь к нашему руководству о краулинге JavaScript-сайтов.

Зачем нужен JS-токен

Crawlbase предлагает два типа токенов. Обычный токен загружает статический HTML; JavaScript (JS) токен сначала рендерит страницу в реальном браузере. Instagram является клиентским рендерингом, поэтому здесь нужен JS-токен. Обычный токен возвращает ту же оболочку, что и обычный запрос, и извлечь из неё ничего полезного невозможно.

Предварительные требования

Несколько вещей, которые нужно подготовить заранее. Это не займёт много времени.

Базовые знания Python. Вы должны уметь запускать скрипты и устанавливать пакеты через pip. Если вы только начинаете изучать парсинг HTML, наше вводное руководство как использовать BeautifulSoup в Python охватывает сторону извлечения.

Python 3.8 или выше. Проверьте командой python --version. Если Python не установлен, скачайте его с python.org.

Аккаунт Crawlbase и JS-токен. Зарегистрируйтесь, откройте панель управления и скопируйте JavaScript (JS) токен со страницы документации аккаунта. Обращайтесь с ним как с паролем: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.

Настройка проекта

Создайте изолированное виртуальное окружение, затем установите две библиотеки, необходимые скраперу.

bash
python --version

python -m venv instagram_env
source instagram_env/bin/activate

pip install crawlbase beautifulsoup4

В Windows активируйте с помощью instagram_env\Scripts\activate вместо строки с source. Две зависимости выполняют работу: crawlbase является официальным клиентом для Crawling API, а beautifulsoup4 парсит возвращаемый HTML, позволяя извлекать отдельные поля по селектору.

Шаг 1: Загрузка отрендеренного профиля

Начните с получения готовой страницы. Импортируйте CrawlingAPI, инициализируйте его своим JS-токеном и запросите URL публичного профиля. Проверяйте код статуса перед парсингом, чтобы ошибки были явными, а не скрытыми.

python
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"})

def crawl(page_url):
    options = {"ajax_wait": "true", "page_wait": 5000}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['status_code']}")
    return None

if __name__ == "__main__":
    page_url = "https://www.instagram.com/nasa/"
    html = crawl(page_url)
    print(html[:500] if html else "No HTML returned")

Два параметра ожидания важны для цели с клиентским рендерингом. Параметр ajax_wait говорит API ждать завершения загрузки асинхронного контента, а page_wait выдерживает фиксированное количество миллисекунд после загрузки, чтобы поздно рендерящиеся элементы успели появиться до захвата страницы. Пять секунд, разумная отправная точка; увеличьте значение, если поля возвращаются пустыми. В примере используется публичный аккаунт организации (NASA) именно потому, что он публичный и безличный. Запустите скрипт, и вы должны увидеть настоящую разметку профиля, что подтверждает работу рендеринга перед написанием единственного селектора.

Crawlbase Crawling API

Instagram требует отрендеренной страницы за доверенным IP в одном вызове. Crawling API принимает JS-токен, запускает страницу в реальном браузере, на стороне сервера ротирует резидентные IP и передаёт вам готовый HTML, поэтому вам не нужно самостоятельно управлять парком headless-браузеров и пулом прокси. Попробуйте на публичном профиле в рамках бесплатного тарифа.

Шаг 2: Парсинг публичных полей с BeautifulSoup

Имея отрендеренный HTML, загрузите его в BeautifulSoup и извлеките публичные поля. Instagram содержит много полезных метаданных в тегах <meta> страницы и во встроенном блоке JSON-LD, что надёжнее, чем отслеживание глубоко вложенных, часто переименовываемых CSS-классов. Имя пользователя и описание профиля находятся в стандартных мета-тегах; постоянные ссылки на публикации, в атрибутах href якорей, следующих шаблону /p/<shortcode>/.

python
import re
from bs4 import BeautifulSoup

def meta(soup, prop):
    el = soup.find("meta", attrs={"property": prop})
    return el["content"] if el and el.has_attr("content") else None

def scrape_profile(html):
    soup = BeautifulSoup(html, "html.parser")

    username = meta(soup, "og:title")
    summary = meta(soup, "og:description")

    post_urls = []
    for a in soup.select("a[href^='/p/']"):
        href = a["href"]
        url = f"https://www.instagram.com{href}"
        if url not in post_urls:
            post_urls.append(url)

    return {
        "username": username,
        "summary": summary,
        "post_urls": post_urls,
    }

Тег og:description в публичном профиле обычно содержит агрегированные публичные счётчики (подписчики, подписки, публикации) в виде единой строки. Воспринимайте их исключительно как публичные агрегаты, но не как способ перечислить стоящих за ними людей. URL публикаций собираются из якорей и дедуплицируются, поскольку одна и та же постоянная ссылка может встречаться в отрендеренном DOM несколько раз.

Селекторы устаревают

Instagram меняет разметку и имена классов без предупреждения, именно поэтому этот код опирается на мета-теги и стабильный шаблон URL /p/<shortcode>/, а не на хрупкие вложенные классы. Когда поле возвращается как None, заново проверьте живую страницу в инструментах разработчика браузера и обновите селектор. Периодическое обслуживание нормально для любого производственного скрапера, это не признак неисправности.

Шаг 3: Извлечение публичных полей из отдельной публикации

Страница публичной публикации содержит те же типы мета-данных и JSON-LD. Из неё можно извлечь публичную подпись и публичное количество лайков и комментариев. Instagram встраивает скрипт application/ld+json на страницах публикаций, который часто содержит блок interactionStatistic с этими агрегированными числами и текстом подписи. Разбор JSON-LD надёжнее, чем парсинг отрендеренных виджетов.

python
import json
from bs4 import BeautifulSoup

def scrape_post(html):
    soup = BeautifulSoup(html, "html.parser")
    block = soup.find("script", attrs={"type": "application/ld+json"})
    if not block:
        return {}

    data = json.loads(block.string)
    likes = comments = None
    for stat in data.get("interactionStatistic", []):
        kind = stat.get("interactionType", "")
        count = stat.get("userInteractionCount")
        if "LikeAction" in kind:
            likes = count
        elif "CommentAction" in kind:
            comments = count

    return {
        "caption": data.get("caption") or data.get("articleBody"),
        "like_count": likes,
        "comment_count": comments,
    }

Это извлекает только агрегированные, неличностные поля: текст подписи, публичное количество лайков и публичное количество комментариев. Здесь не читаются отдельные комментарии, хендлы комментаторов или кто поставил лайк. Такое ограничение намеренно, и именно оно делает работу обоснованной. Количество лайков и комментариев, это числа; люди, стоящие за ними, не являются вашим материалом для сбора.

Шаг 4: Объединение

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

python
import json
import time
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"})

def crawl(page_url):
    options = {"ajax_wait": "true", "page_wait": 5000}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['status_code']}")
    return None

def main():
    profile_url = "https://www.instagram.com/nasa/"
    html = crawl(profile_url)
    if not html:
        return

    profile = scrape_profile(html)
    records = []
    for post_url in profile["post_urls"][:5]:
        post_html = crawl(post_url)
        if post_html:
            record = scrape_post(post_html)
            record["url"] = post_url
            records.append(record)
        time.sleep(3)

    output = {"username": profile["username"], "posts": records}
    print(json.dumps(output, indent=2, ensure_ascii=False))

if __name__ == "__main__":
    main()

Пауза time.sleep(3) между запросами не является украшением. Темп запросов, это единственный наиболее важный фактор, определяющий работоспособность парсера, и мы вернёмся к этому. Срез [:5] делает демонстрацию небольшой; увеличивайте его только тогда, когда ваш темп и объём будут ответственными.

Как выглядит результат

Запустите полный скрипт и вы получите чистую запись публичных полей, готовую для записи в JSON, CSV или базу данных.

json
{
  "username": "NASA (@nasa)",
  "posts": [
    {
      "caption": "A new view of a distant galaxy cluster.",
      "like_count": 412338,
      "comment_count": 1894,
      "url": "https://www.instagram.com/p/Cxample123/"
    }
  ]
}

Как оставаться незаблокированным

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

  • Соблюдайте темп запросов. Быстрая отправка запросов в тесном цикле, самый быстрый способ получить блокировку. Добавляйте реальные задержки, как в примере с time.sleep выше, и не торопитесь с агрессивной параллелизацией.
  • Опирайтесь на ротацию. Пул резидентных IP распределяет запросы по многим адресам реальных пользователей, чтобы ни один из них не превысил лимит. Crawling API делает это за вас; если вы строите собственный стек, именно эта часть требует тщательной проработки. Наше руководство как использовать ротируемые прокси рассматривает это подробнее.
  • Следите за кодами статуса. Запуск, возвращающий проверки или ошибки, сигнализирует о том, что текущий темп или уровень IP больше недостаточны. Снижайте темп, не давите сильнее.
  • Поддерживайте низкий объём и разнообразие целей. Исследование публичных данных не требует обхода всей истории аккаунта. Возьмите необходимую выборку и остановитесь.

Для изучения общей стратегии смотрите руководство как обойти captcha при веб-скрапинге и углублённый материал о парсинге JavaScript-страниц с Python. Если вы предпочитаете направлять собственный трафик через ротируемый пул, а не использовать управляемый API, Smart AI Proxy предоставляет ту же резидентную ротацию в качестве прокси-эндпоинта.

Легально ли парсить Instagram?

Это раздел, который следует прочитать перед написанием производственного кода. Instagram принадлежит Meta, и Условия использования Meta строго ограничивают автоматический доступ и сбор данных. Автоматический парсинг может противоречить этим условиям вне зависимости от тщательности вашего инструментария, и ни один из вышеприведённых кодов не меняет этого. Он лишь обеспечивает техническую сторону. Прочитайте Условия использования Meta и Instagram, а также robots.txt Instagram, и воспринимайте оба документа как границы того, что вы собираете.

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

Для любого реального или коммерческого использования правильным инструментом является официальный Instagram Graph API. Он создан для санкционированного доступа к аккаунтам, которыми вы владеете или управляете, обеспечивает гарантированную структуру и позволяет вам оставаться в рамках условий Meta. Эта статья является техническим руководством, строго ограниченным публичными данными из публичных аккаунтов. Она не является одобрением массового сбора персональных данных и не охватывает ничего, что находится за входом в систему. Если вашему проекту нужно больше, чем небольшая выборка публичных полей, Graph API или официальное соглашение об обмене данными является правильным путём, а не более изощрённый скрапер.

Итоги

Ключевые выводы

  • Instagram использует клиентский рендеринг и защищён от ботов. Обычный запрос возвращает пустую оболочку, поэтому необходимо отрендерить страницу перед парсингом.
  • Рендеринг и доверенный IP должны быть в одном вызове. Crawling API с JS-токеном обеспечивает оба; параметры ajax_wait и page_wait управляют временем ожидания контента.
  • Парсите стабильные сигналы. Мета-теги, шаблон URL /p/<shortcode>/ и JSON-LD надёжнее, чем хрупкие вложенные классы.
  • Только публичные агрегаты. Извлекайте имя пользователя, подписи, количество лайков и комментариев, а также URL публикаций; никогда не берите списки подписчиков, личности комментаторов или частный контент.
  • Соблюдайте темп, используйте ротацию и предпочитайте Graph API. Поддерживайте низкий объём, опирайтесь на резидентную ротацию и используйте официальный Instagram Graph API для реального или коммерческого использования.

Часто задаваемые вопросы

Почему обычный запрос не возвращает данные из Instagram?

Потому что Instagram рендерит контент профилей и публикаций на стороне клиента с помощью JavaScript. Исходный HTML является оболочкой, которая заполняется только после того, как скрипты страницы выполняются в браузере, поэтому обычный HTTP-запрос возвращает почти пустое тело. Чтобы получить настоящие публичные данные, необходимо сначала отрендерить страницу, именно это JS-токен Crawling API делает за вас.

Нужен ли обычный токен или JS-токен для Instagram?

JS-токен. Обычный токен загружает статический HTML, который в Instagram представляет ту же пустую оболочку, что и обычный запрос. JS-токен рендерит страницу в реальном браузере перед возвратом HTML, так что публичные поля присутствуют при их парсинге с BeautifulSoup.

Какие данные Instagram безопасно парсить?

Только публичные данные из публичных аккаунтов: публичное имя пользователя, публичные подписи к публикациям, публичное количество лайков и комментариев в виде агрегированных чисел, а также URL публичных публикаций. Закрытые аккаунты, контент за входом в систему, личные сообщения, списки подписчиков и подписок, а также личности отдельных комментаторов или тех, кто поставил лайк, находятся под запретом. Это персональные данные, и их сбор противоречит условиям Meta и во многих местах нарушает закон о конфиденциальности.

Стоит ли использовать официальный Instagram Graph API или парсить сайт?

Для любого реального, постоянного или коммерческого использования используйте официальный Instagram Graph API. Это санкционированный путь, обеспечивающий гарантированную структуру и позволяющий оставаться в рамках условий Meta. Парсинг небольшой выборки публичных полей подходом, описанным здесь, приемлем для лёгкого исследования публичных данных, когда доступ к API не настроен, при условии соблюдения условий, robots.txt и лимитов запросов.

Как избежать блокировки при парсинге Instagram?

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

Можно ли парсить закрытые аккаунты или списки подписчиков?

Нет, и это руководство намеренно не показывает как. Контент закрытых аккаунтов находится за аутентификацией, а списки подписчиков и личности отдельных пользователей являются персональными данными. Парсинг контента за входом в систему, перечисление подписчиков или обход аутентификации для доступа к чему-либо из этого выходит за рамки данного руководства и противоречит условиям Meta. Для санкционированного доступа к аккаунтам, которыми вы владеете или управляете, официальный Instagram Graph API является правильным путём.

Начать создавать

Обходите любой сайт в масштабе, без борьбы с инфраструктурой.

Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

Самообслуживание · Звонок отдела продаж не требуется · Доступны корпоративные объёмы краулинга