es
English
中國人
Tiếng Việt
Deutsch
Українська
Português
Français
भारतीय
Türkçe
한국인
Italiano
Indonesia
Polski Obtener acceso a los datos de Instagram puede ser complicado debido a diversos mecanismos anti-bot, requisitos de inicio de sesión y límites de velocidad. Sin embargo, puedes extraer información útil de perfiles públicos con las herramientas y técnicas adecuadas. Este artículo te guiará sobre cómo scrapear datos de usuarios de Instagram usando Python haciendo peticiones API al backend de Instagram, extrayendo información de los datos JSON devueltos y guardándola en un archivo JSON.
Antes de adentrarnos en el código, asegúrate de tener instaladas las librerías de Python necesarias.
pip install requests python-box
Vamos a dividir el código en diferentes secciones para una mejor comprensión, incluyendo el envío de la petición, la obtención y el análisis sintáctico de los datos, el uso de proxies para evitar ser detectados y la simplificación del análisis sintáctico de JSON con la librería Box.
El frontend de Instagram está fuertemente protegido, pero el backend ofrece puntos finales de la API que se pueden utilizar sin autenticación. Usaremos uno de estos puntos en adelante.
Esta API proporciona información detallada sobre el perfil de un usuario, incluyendo su descripción, número de seguidores y publicaciones. Vamos a explorar cómo solicitar datos utilizando la biblioteca requests en Python.
Explicación:
import requests
# Define las cabeceras para imitar una petición real del navegador
headers = {
"x-ig-app-id": "936619743392459", # ID de la aplicación de Instagram para autenticar la solicitud
"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": "*/*",
}
# Sustitúyalo por el nombre de usuario que desea raspar
username = 'testtest'
# Enviar una solicitud API para obtener los datos del perfil
response = requests.get(f'https://i.instagram.com/api/v1/users/web_profile_info/?username={username}', headers=headers)
response_json = response.json() # Parsear la respuesta en un objeto JSON
Dado que Instagram restringe las solicitudes repetidas desde la misma dirección IP, si necesitas comprar proxy para el scraping a gran escala, es importante elegir direcciones estables y de buena calidad. Un proxy enruta tus peticiones a través de diferentes direcciones IP, y si necesitas comprar proxy España para una ubicación concreta, también puede ayudarte a trabajar con un contexto regional específico.
Para configurar un servidor proxy, necesitarás la dirección IP, el número de puerto y, si es necesario, un nombre de usuario y una contraseña para la autenticación.
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)
La API de Instagram devuelve una compleja estructura JSON anidada, que puede ser difícil de navegar utilizando el acceso tradicional basado en diccionarios. Para facilitar el parseo, podemos usar la librería Box, que permite acceder a datos JSON usando notación de puntos en lugar de claves de diccionario.
Explicación:
from box import Box
response_json = Box(response.json())
# Extraer los datos del perfil del usuario
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,
}
Una vez extraídos los datos del perfil, también podemos scrapear los datos de la línea de tiempo de vídeo del usuario y las publicaciones habituales.
Explicación:
# Extraer datos de vídeo
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)
# Extraer datos multimedia de la línea de tiempo (fotos y vídeos)
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)
Una vez extraídos todos los datos, el siguiente paso es guardarlos en un archivo JSON para su posterior análisis o almacenamiento. Utilizamos el módulo json de Python para escribir los datos extraídos en archivos JSON. Cada archivo tendrá un formato ordenado, gracias al parámetro indent=4, que facilita la lectura y el procesamiento de los datos.
import json
# Guardar los datos del usuario en un archivo JSON
with open(f'{username}_profile_data.json', 'w') as file:
json.dump(user_data, file, indent=4)
# Guardar datos de vídeo en un archivo JSON
with open(f'{username}_video_data.json', 'w') as file:
json.dump(profile_video_data, file, indent=4)
# Guardar los datos multimedia de la línea de tiempo en un archivo JSON
with open(f'{username}_timeline_media_data.json', 'w') as file:
json.dump(profile_timeline_media_data, file, indent=4)
Aquí está el script Python completo que combina todas las secciones discutidas anteriormente. Este código scrapea los datos de perfil de usuario, los datos de vídeo y los datos multimedia de la línea de tiempo de Instagram, gestiona las cabeceras y proxies necesarios y guarda la información extraída en archivos JSON.
import requests
from box import Box
import json
# Encabezados para imitar una solicitud real del navegador a la API de 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": "*/*",
}
# Establecer un proxy para evitar la limitación de velocidad y la detección (opcional)
proxies = {
'http': 'http://<proxy_username>:<proxy_password>@<proxy_ip>:<proxy_port>',
'https': 'https://<proxy_username>:<proxy_password>@<proxy_ip>:<proxy_port>',
}
# El nombre de usuario de Instagram a raspar
username = 'testtest'
# Enviar una solicitud a la API de Instagram para obtener los datos del perfil
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()) # Convertir la respuesta en un objeto Box para facilitar la navegación
# Extraer datos del perfil del usuario
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,
}
# Extraer datos de vídeo de la línea de tiempo de vídeo del usuario
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)
# Extraer datos multimedia de la línea de tiempo (fotos y vídeos)
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)
# Guardar los datos del perfil del usuario en un archivo 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')
# Guardar datos de vídeo en un archivo 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')
# Guardar los datos multimedia de la línea de tiempo en un archivo 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')
El scraping de datos de Instagram con Python se puede hacer aprovechando la API backend proporcionada por Instagram, que ayuda a eludir algunas de las restricciones front-end. Utilizar las cabeceras adecuadas para imitar el comportamiento del navegador y emplear proxies residenciales para evitar la limitación de velocidad son pasos críticos. La biblioteca Box simplifica aún más el proceso haciendo que el análisis sintáctico de JSON sea más intuitivo gracias a la notación de puntos. Antes de empezar a scrapear Instagram a escala, recuerda cumplir con los términos de servicio de Instagram, y asegúrate de que tus esfuerzos de scraping no violan sus políticas.
Comentarios: 0