Як скрапити дані 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 Коментаріїв