Как скрапить данные Instagram с использованием Python

Комментарии: 0

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

Настройка необходимых библиотек

Перед началом работы убедитесь, что установлены требуемые библиотеки Python.


pip install requests python-box

  • requests: для выполнения HTTP-запросов;
  • python-box: упрощает доступ к данным, преобразуя словари в объекты, которые позволяют доступ к атрибутам через точечную нотацию.

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

Шаг 1. Отправка API запроса

Фронтенд Instagram защищен очень серьезно, однако бэкенд предоставляет API-end points, которые можно использовать без авторизации. Одну из таких точек мы используем в дальнейшем.

Этот API предоставляет подробную информацию о профиле пользователя, включая его описание, количество подписчиков и публикации. Рассмотрим, как можно запросить данные с помощью библиотеки requests в Python.

Объяснение кода:

  1. Заголовки: Instagram блокирует большинство запросов ботов, анализируя заголовки запросов. x-ig-app-id критически важен, так как имитирует запрос, исходящий непосредственно от приложения Instagram. Строка User-Agent представляет браузер, совершающий запрос, вводя Instagram в заблуждение, будто это запрос от реального пользователя.
  2. Запрос к бэкенду API: URL https://i.instagram.com/api/v1/users/web_profile_info/?username={username} является частью бэкенда API Instagram. Он предоставляет подробную информацию о публичном профиле.
  3. Обработка JSON ответа: Мы используем response.json() для преобразования ответа API в JSON-объект, который мы можем легко анализировать и извлекать информацию.

import requests

# Определение заголовков для имитации запроса от реального браузера
headers = {
    "x-ig-app-id": "936619743392459",  # ID приложения Instagram для аутентификации запроса
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9,ru;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept": "*/*",
}

# Замените это на имя пользователя, которое хотите скрапить
username = 'testtest'

# Отправка API запроса для получения данных профиля
response = requests.get(f'https://i.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=headers)
response_json = response.json()  # Преобразование ответа в JSON-объект

Шаг 2. Применение прокси для обхода ограничений по частоте запросов

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

Для настройки прокси-сервера требуются IP-адрес, порт, а также имя пользователя и пароль, если это необходимо.


proxies = {
    'http': 'http://<proxy_username>:<proxy_password>@<proxy_ip>:<proxy_port>',
    'https': 'https://<proxy_username>:<proxy_password>@<proxy_ip>:<proxy_port>',
}

response = requests.get(f'https://i.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=headers, proxies=proxies)

Шаг 3. Упрощение парсинга JSON с помощью Box

API Instagram возвращает сложную вложенную структуру JSON, навигация по которой с использованием традиционного доступа на основе словаря может быть затруднительной. Для упрощения парсинга можно использовать библиотеку Box.

Объяснение:

  1. Box: Эта библиотека преобразует словарь JSON в объект, позволяя обращаться к глубоко вложенным полям с использованием точечной нотации. Например, вместо response_json['data']['user']['full_name'] можно просто написать response_json.data.user.full_name.
  2. Извлечение данных: Извлекается полезная информация о профиле пользователя, такая как полное имя, ID, описание, является ли аккаунт бизнес- или профессиональным, статус верификации, количество подписчиков.

from box import Box

response_json = Box(response.json())

# Извлечение данных профиля пользователя
user_data = {
    'full name': response_json.data.user.full_name,
    'id': response_json.data.user.id,
    'biography': response_json.data.user.biography,
    'business account': response_json.data.user.is_business_account,
    'professional account': response_json.data.user.is_professional_account,
    'category name': response_json.data.user.category_name,
    'is verified': response_json.data.user.is_verified,
    'profile pic url': response_json.data.user.profile_pic_url_hd,
    'followers': response_json.data.user.edge_followed_by.count,
    'following': response_json.data.user.edge_follow.count,
}

Шаг 4. Извлечение данных видео и таймлайна

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

Объяснение:

  1. Video data: этот раздел извлекает данные о видео пользователя на Instagram, включая URL видео, количество просмотров, количество комментариев и длительность видео.
  2. Timeline media: аналогично, этот раздел извлекает данные из таймлайна пользователя, захватывая URL медиа публикаций, лайки и комментарии.

# Извлечение данных видео
profile_video_data = []
for element in response_json.data.user.edge_felix_video_timeline.edges:
    video_data = {
        'id': element.node.id,
        'short code': element.node.shortcode,
        'video url': element.node.video_url,
        'view count': element.node.video_view_count,
        'comment count': element.node.edge_media_to_comment.count,
        'like count': element.node.edge_liked_by.count,
        'duration': element.node.video_duration,
    }
    profile_video_data.append(video_data)

# Извлечение данных медиа таймлайна (фото и видео)
profile_timeline_media_data = []
for element in response_json.data.user.edge_owner_to_timeline_media.edges:
    media_data = {
        'id': element.node.id,
        'short code': element.node.shortcode,
        'media url': element.node.display_url,
        'comment count': element.node.edge_media_to_comment.count,
        'like count': element.node.edge_liked_by.count,
    }
    profile_timeline_media_data.append(media_data)

Шаг 5. Сохранение данных в файлы JSON

После извлечения всех данных следующим шагом является их сохранение в файл JSON для дальнейшего анализа или хранения.

Для записи извлеченных данных в файлы JSON используется модуль json Python. Каждый файл будет аккуратно отформатирован благодаря параметру indent=4, что облегчает чтение и обработку данных.


import json

# Сохранение данных пользователя в файл JSON
with open(f'{username}_profile_data.json', 'w') as file:
    json.dump(user_data, file, indent=4)

# Сохранение данных видео в файл JSON
with open(f'{username}_video_data.json', 'w') as file:
    json.dump(profile_video_data, file, indent=4)

# Сохранение данных медиа таймлайна в файл JSON
with open(f'{username}_timeline_media_data.json', 'w') as file:
    json.dump(profile_timeline_media_data, file, indent=4)

Финальная версия кода

Ниже представлен полный Python скрипт, объединяющий все ранее обсуждаемые разделы.


import requests
from box import Box
import json

# Заголовки для имитации реального браузерного запроса к бэкенду API Instagram
headers = {
    "x-ig-app-id": "936619743392459", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9,ru;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept": "*/*",
}

# Настройка прокси для избежания ограничений по частоте запросов и обнаружения (опционально)
proxies = {
    'http': 'http://<proxy_username>:<proxy_password>@<proxy_ip>:<proxy_port>',
    'https': 'https://<proxy_username>:<proxy_password>@<proxy_ip>:<proxy_port>',
}

# Имя пользователя Instagram для скрапинга
username = 'testtest'

# Отправка запроса к бэкенду API Instagram для получения данных профиля
response = requests.get(f'https://i.instagram.com/api/v1/users/web_profile_info/?username={username}', 
                        headers=headers, proxies=proxies)
response_json = Box(response.json())  # Преобразование ответа в объект Box для удобной навигации

# Извлечение данных профиля пользователя
user_data = {
    'full name': response_json.data.user.full_name,
    'id': response_json.data.user.id,
    'biography': response_json.data.user.biography,
    'business account': response_json.data.user.is_business_account,
    'professional account': response_json.data.user.is_professional_account,
    'category name': response_json.data.user.category_name,
    'is verified': response_json.data.user.is_verified,
    'profile pic url': response_json.data.user.profile_pic_url_hd,
    'followers': response_json.data.user.edge_followed_by.count,
    'following': response_json.data.user.edge_follow.count,
}

# Извлечение данных видео из видео таймлайна пользователя
profile_video_data = []
for element in response_json.data.user.edge_felix_video_timeline.edges:
    video_data = {
        'id': element.node.id,
        'short code': element.node.shortcode,
        'video url': element.node.video_url,
        'view count': element.node.video_view_count,
        'comment count': element.node.edge_media_to_comment.count,
        'like count': element.node.edge_liked_by.count,
        'duration': element.node.video_duration,
    }
    profile_video_data.append(video_data)

# Извлечение данных медиа из таймлайна пользователя (фото и видео)
profile_timeline_media_data = []
for element in response_json.data.user.edge_owner_to_timeline_media.edges:
    media_data = {
        'id': element.node.id,
        'short code': element.node.shortcode,
        'media url': element.node.display_url,
        'comment count': element.node.edge_media_to_comment.count,
        'like count': element.node.edge_liked_by.count,
    }
    profile_timeline_media_data.append(media_data)

# Сохранение данных профиля пользователя в файл JSON
with open(f'{username}_profile_data.json', 'w') as file:
    json.dump(user_data, file, indent=4)
print(f'saved json: {username}_profile_data.json')

# Сохранение данных видео в файл JSON
with open(f'{username}_video_data.json', 'w') as file:
    json.dump(profile_video_data, file, indent=4)
print(f'saved json: {username}_video_data.json')

# Сохранение данных медиа таймлайна в файл JSON
with open(f'{username}_timeline_media_data.json', 'w') as file:
    json.dump(profile_timeline_media_data, file, indent=4)
print(f'saved json: {username}_timeline_media_data.json')

Скрапинг данных с Instagram можно выполнить через бэкенд API, предложенный самой платформой. Этот подход позволяет обходить ограничения, установленные на уровне пользовательского интерфейса. Ключевым аспектом успешного сбора данных является использование корректно сформированных заголовков запросов для имитации поведения браузера, а также применение прокси-серверов для предотвращения блокировок по причине превышения допустимой частоты запросов. Библиотека Box значительно упрощает обработку JSON-данных, позволяя обращаться к ним с помощью точечной нотации, что делает процесс более интуитивно понятным. Однако перед началом масштабного сбора данных важно удостовериться, что такие действия не противоречат условиям использования Instagram и не нарушают их политики.

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

0 комментариев