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-сайтов.
Crawlbase предлагает два типа токенов. Обычный токен загружает статический HTML; JavaScript (JS) токен сначала рендерит страницу в реальном браузере. Instagram является клиентским рендерингом, поэтому здесь нужен JS-токен. Обычный токен возвращает ту же оболочку, что и обычный запрос, и извлечь из неё ничего полезного невозможно.
Предварительные требования
Несколько вещей, которые нужно подготовить заранее. Это не займёт много времени.
Базовые знания Python. Вы должны уметь запускать скрипты и устанавливать пакеты через pip. Если вы только начинаете изучать парсинг HTML, наше вводное руководство как использовать BeautifulSoup в Python охватывает сторону извлечения.
Python 3.8 или выше. Проверьте командой python --version. Если Python не установлен, скачайте его с python.org.
Аккаунт Crawlbase и JS-токен. Зарегистрируйтесь, откройте панель управления и скопируйте JavaScript (JS) токен со страницы документации аккаунта. Обращайтесь с ним как с паролем: он аутентифицирует ваши запросы, поэтому не добавляйте его в систему контроля версий.
Настройка проекта
Создайте изолированное виртуальное окружение, затем установите две библиотеки, необходимые скраперу.
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 публичного профиля. Проверяйте код статуса перед парсингом, чтобы ошибки были явными, а не скрытыми.
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) именно потому, что он публичный и безличный. Запустите скрипт, и вы должны увидеть настоящую разметку профиля, что подтверждает работу рендеринга перед написанием единственного селектора.
Instagram требует отрендеренной страницы за доверенным IP в одном вызове. Crawling API принимает JS-токен, запускает страницу в реальном браузере, на стороне сервера ротирует резидентные IP и передаёт вам готовый HTML, поэтому вам не нужно самостоятельно управлять парком headless-браузеров и пулом прокси. Попробуйте на публичном профиле в рамках бесплатного тарифа.
Шаг 2: Парсинг публичных полей с BeautifulSoup
Имея отрендеренный HTML, загрузите его в BeautifulSoup и извлеките публичные поля. Instagram содержит много полезных метаданных в тегах <meta> страницы и во встроенном блоке JSON-LD, что надёжнее, чем отслеживание глубоко вложенных, часто переименовываемых CSS-классов. Имя пользователя и описание профиля находятся в стандартных мета-тегах; постоянные ссылки на публикации, в атрибутах href якорей, следующих шаблону /p/<shortcode>/.
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 надёжнее, чем парсинг отрендеренных виджетов.
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: Объединение
Теперь объедините загрузку и парсинг в один рабочий скрипт, который читает публичный профиль, а затем посещает первые несколько публичных публикаций.
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 или базу данных.
{ "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 запросов бесплатно, без карты.
