Raspado de datos de productos de Amazon con Python

Comentarios: 0

Acceder a los datos de gigantes del comercio electrónico como Amazon es crucial para el análisis del mercado, las estrategias de precios y la investigación de productos. Estos datos pueden recopilarse mediante web scraping, un método que consiste en extraer grandes cantidades de información de sitios web. Sin embargo, Amazon protege rigurosamente sus datos, por lo que las técnicas tradicionales de scraping suelen ser ineficaces. En esta completa guía, profundizaremos en los métodos de recopilación de datos de productos de Amazon y discutiremos estrategias para eludir los robustos sistemas anti-scraping de la plataforma. Exploraremos el uso de Python, proxies y técnicas avanzadas de scraping que pueden ayudar a superar estos desafíos y recopilar de manera eficiente los datos necesarios para su negocio o para fines de investigación.

Creación de un script Python para scrapear datos de Amazon

Para extraer datos de Amazon con éxito, puede seguir el algoritmo estructurado que se describe a continuación. Este método garantiza la recuperación de la información necesaria de forma eficaz y precisa.

Paso 1: Envío de peticiones HTTP a páginas de productos de Amazon:

  • Utilice la biblioteca de peticiones para iniciar peticiones HTTP GET dirigidas a las páginas de productos de Amazon;
  • Captura el contenido HTML sin procesar de la respuesta HTTP para prepararlo para el análisis sintáctico.

Paso 2: Análisis del contenido HTML:

  • Utiliza la biblioteca lxml para analizar el contenido HTML recibido;
  • Analice el HTML para localizar los puntos de datos específicos que desea extraer;
  • Ejecute consultas XPath para dirigir y extraer con precisión estos puntos de datos de la estructura HTML.

Paso 3: Almacenamiento de los datos:

  • Una vez extraídos los datos necesarios, proceda a guardarlos en formatos accesibles como CSV o JSON, que facilitan su análisis e integración con otras aplicaciones.

Manejar los posibles obstáculos

Amazon emplea varias medidas para dificultar los esfuerzos de scraping, como limitaciones de velocidad de conexión, integración de CAPTCHA y bloqueo de IP. Los usuarios pueden adoptar contramedidas para sortear estos obstáculos, como utilizar proxies de alta calidad.

Para actividades de scraping extensivas, se pueden emplear técnicas avanzadas de Python para recopilar cantidades sustanciales de datos de productos. Estas técnicas incluyen el relleno de cabeceras y el TLS fingerprinting, que ayudan a evitar la detección y garantizan el éxito de la extracción de datos.

Estos pasos se explican en las próximas secciones del artículo donde se verá su implementación práctica utilizando Python 3.12.2

Requisitos previos

Para iniciar un proyecto de web scraping, comenzaremos por configurar un scraper básico utilizando la biblioteca lxml para el análisis sintáctico de HTML y la biblioteca requests para gestionar las solicitudes HTTP dirigidas al servidor web de Amazon.

Nos centraremos en extraer información esencial como nombres de productos, precios y valoraciones de las páginas de productos de Amazon. También mostraremos técnicas para analizar eficientemente HTML y gestionar peticiones, asegurando una extracción precisa y organizada de los datos.

Para mantener las dependencias del proyecto y evitar conflictos, es aconsejable crear un entorno virtual separado para este esfuerzo de web scraping. Se recomienda utilizar herramientas como "venv" o "pyenv" para crear entornos virtuales.

Instalar bibliotecas de terceros

Necesitarás las siguientes bibliotecas de Python de terceros:

1. requests

Se utiliza para enviar peticiones HTTP y recuperar contenido web. Suele utilizarse para el web scraping y para interactuar con las API web.

Instalación:

 pip install requests

2. lxml

Biblioteca para analizar y manipular documentos XML y HTML. Se utiliza con frecuencia para el web scraping y para trabajar con datos estructurados de páginas web.

Instalación:

 pip install lxml

Importación de las bibliotecas necesarias

Aquí necesitamos importar las librerías necesarias para que nuestro scraper funcione. Que incluye una biblioteca de solicitud para el manejo de solicitudes HTTP, biblioteca CSV para el manejo de la operación de archivos CSV, la biblioteca aleatoria para generar valores aleatorios y hacer elecciones al azar, lxml biblioteca para analizar el contenido HTML en bruto, y Dict y List para el tipo de sugerencia.

 import requests
import csv
import random
from lxml import html
from typing import Dict, List

Lectura de entradas del archivo CSV

El siguiente fragmento de código lee un archivo CSV llamado amazon_product_urls.csv donde cada línea contiene la URL de una página de producto de Amazon. El código itera sobre las filas, extrayendo las URL de cada fila y añadiéndolas a una lista llamada URL.

 with open('amazon_product_urls.csv', 'r') as file:
    reader = csv.DictReader(file)
    for row in reader:
        urls.append(row['url'])

Cabeceras de petición HTTP y proxies

Las cabeceras de solicitud desempeñan un papel importante en las solicitudes HTTP, ya que proporcionan información compleja sobre el cliente y la solicitud. Durante el scraping, es importante copiar los títulos de usuario autorizados para evitar la detección y acceder fácilmente a la información que se desea. Al imitar cabeceras de uso común, los scrapers pueden evitar las técnicas de detección, garantizando que los datos se extraen de forma coherente y manteniendo las normas éticas.

Los proxies actúan como intermediarios en el web scraping, enmascarando la dirección IP del scraper para evitar la detección y el bloqueo del servidor. Un proxy rotatorio permite enviar cada solicitud con una nueva dirección IP evitando posibles bloqueos.. El uso de proxies residenciales o móviles refuerza la resistencia a las medidas anti-scraping debido a la detección real del host y del proveedor.

Código para integrar cabeceras de petición y servidores proxy con autorización de dirección IP:

 headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'dnt': '1',
    'sec-ch-ua': '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
   }
proxies = {'http': '', 'https': ''}

Rotación del agente de usuario

Aquí, crearemos una lista de colecciones de agentes de usuario, de la que se elegirá un agente de usuario aleatorio para cada petición. Implementar un mecanismo de rotación de encabezados, como rotar el User-Agent después de cada solicitud, puede ayudar aún más a eludir las medidas de detección de bots.

 useragents = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4591.54 Safari/537.36",
        "Mozilla/5.0 (Windows NT 7_0_2; Win64; x64) AppleWebKit/541.38 (KHTML, like Gecko) Chrome/105.0.1585 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.7863.44 Safari/537.36"
    ]
headers['user-agent'] = random.choice(useragnets)

Realizar peticiones HTTP a la página de productos de Amazon junto con cabeceras y proxy

Envía una petición HTTP GET a una URL especificada con cabeceras personalizadas, un tiempo de espera de 30 segundos y los proxies especificados para la petición.

response = requests.get(url=url, headers=headers, proxies=proxies, timeout=30)

Identificación de XPath/Selectores de puntos de datos necesarios

Puntos de datos requeridos: título, precio y valoraciones. Ahora, inspeccionemos e identifiquemos el XPath correspondiente para los elementos mostrados en las capturas de pantalla junto con sus respectivos puntos de datos.

La siguiente captura de pantalla muestra la función "Inspeccionar" de Chrome DevTools siendo utilizada para encontrar el XPath `//span[@id="productTitle"]/text()` para extraer el título del producto de una página de producto de Amazon.

1.png

La siguiente captura de pantalla muestra la búsqueda respectiva del XPath `//div[@id="corePrice_feature_div"]/div/div/span/span/text()` para extraer el precio del producto de una página de producto de Amazon.

2.png

La captura de pantalla muestra la búsqueda respectiva del XPath `//span[@id="acrPopover"]/@title'` para extraer las valoraciones de producto de una página de producto de Amazon.

3.png

Cree un diccionario que proporcione expresiones XPath para extraer información específica de una página web: el título, las valoraciones y el precio de un producto.

xpath_queries = {'title': '//span[@id="productTitle"]/text()', 'ratings': '//span[@id="acrPopover"]/@title', 'price': '//span[@class="a-offscreen"]/text()'}

Creación de un analizador lxml a partir de la respuesta HTML

El siguiente código analiza el contenido HTML obtenido de la solicitud GET al servidor de Amazon en un formato estructurado en forma de árbol, lo que permite una navegación y manipulación más sencillas de sus elementos y atributos.

tree = html.fromstring(response.text)

Extracción de los datos necesarios

El siguiente fragmento de código extrae datos del árbol HTML analizado mediante una consulta XPath y los asigna a un diccionario con una clave especificada. strip() se utiliza para eliminar los espacios en blanco al principio y al final, si los hay. Recupera el primer resultado de la consulta XPath y lo almacena bajo la clave dada en el diccionario datos_extraídos.

data = tree.xpath(xpath_query)[0].strip()
extracted_data[key] = data

Guardar los datos extraídos en CSV

El siguiente código escribe los datos del diccionario datos_extraídos en un archivo CSV llamado datos_producto.csv. Asegúrate de que la línea de encabezado se escribe sólo si el archivo está vacío. Si el archivo no está vacío, añade los datos como una fila adicional al archivo CSV. Esta función permite actualizar continuamente el fichero CSV con los nuevos datos extraídos sin sobrescribir el texto existente.

 csv_file_path = 'product_data.csv'
fieldnames = ['title', 'ratings', 'price']
with open(csv_file_path, 'a', newline='') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    if csvfile.tell() == 0:
        writer.writeheader()
    writer.writerow(extracted_data)

Aplicación del código

Consulte nuestro código completo, que le ayudará a empezar rápidamente. El código está bien estructurado y documentado, por lo que es fácil de usar para principiantes. Para ejecutar este código, el usuario debe tener un archivo CSV llamado "amazon_product_urls" en el mismo directorio. A continuación se muestra la estructura del archivo CSV:

4.png

import requests
import csv
import random
from lxml import html
from typing import Dict, List


def send_requests(
    url: str, headers: Dict[str, str], proxies: Dict[str, str]
) -> List[Dict[str, str]]:
    """
    Envía peticiones HTTP GET a múltiples URLs con cabeceras y proxies.

    Args:
        urls (str): URL a la que enviar las solicitudes.
        headers (Dict[str, str]): Diccionario que contiene las cabeceras de las peticiones.
        proxies (Dict[str, str]): Diccionario que contiene la configuración del proxy.

    Returns:
        Response: Objeto de respuesta que contiene datos de respuesta para cada URL.
    """
    try:
        response = requests.get(url, headers=headers, proxies=proxies, timeout=30)
        # Validación de la respuesta
        if len(response.text)> 10000:
            return response
        return None
    except Exception as e:
        print(f"Error occurred while fetching URL {url}: {str(e)}")


def extract_data_from_html(
    response, xpath_queries: Dict[str, str]
) -> Dict[str, List[str]]:
    """
    Extrae datos del contenido HTML mediante consultas XPath.

    Args:
        response (Response): Objeto de respuesta.
        xpath_queries (Dict[str, str]): Diccionario que contiene consultas XPath para la extracción de datos.

    Returns:
        Dict[str, str]: Diccionario que contiene los datos extraídos para cada consulta XPath.
    """
    extracted_data = {}
    tree = html.fromstring(response.text)
    for key, xpath_query in xpath_queries.items():
        data = tree.xpath(xpath_query)[0].strip()
        extracted_data[key] = data
    return extracted_data


def save_to_csv(extracted_data: Dict[str, any]):
    """
    Guarda un diccionario como una fila en un archivo CSV utilizando DictWriter.

    Args:
        extracted_data (Dict[str, any]): Diccionario que representa una fila de datos.
    """
    csv_file_path = "product_data.csv"
    fieldnames = ["title", "ratings", "price"]
    with open(csv_file_path, "a", newline="") as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        if csvfile.tell() == 0:
            writer.writeheader()  # Escribir cabecera sólo si el fichero está vacío
        writer.writerow(extracted_data)


def main():
    # Lectura de URL de un archivo CSV
    urls = []
    with open("amazon_product_urls.csv", "r") as file:
        reader = csv.DictReader(file)
        for row in reader:
            urls.append(row["url"])

    # Defining request headers
    headers = {
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "accept-language": "en-IN,en;q=0.9",
        "dnt": "1",
        "sec-ch-ua": '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"Windows"',
        "sec-fetch-dest": "document",
        "sec-fetch-mode": "navigate",
        "sec-fetch-site": "same-origin",
        "sec-fetch-user": "?1",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
    }

    useragents = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4591.54 Safari/537.36",
        "Mozilla/5.0 (Windows NT 7_0_2; Win64; x64) AppleWebKit/541.38 (KHTML, like Gecko) Chrome/105.0.1585 Safari/537.36",
        "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.7863.44 Safari/537.36"
        ]

    # Definición de proxies
    proxies = {"http": "IP:Port", "https": "IP:Port"}

    # Envío de solicitudes a URL
    for url in urls:
        # Rotación de Useragent en las cabeceras
        headers["user-agent"] = random.choice(useragnets)
        response = send_requests(url, headers, proxies)
        if response:
            # Extraer datos del contenido HTML
            xpath_queries = {
                "title": '//span[@id="productTitle"]/text()',
                "ratings": '//span[@id="acrPopover"]/@title',
                "price": '//span[@class="a-offscreen"]/text()',
            }
            extracted_data = extract_data_from_html(response, xpath_queries)

            # Guardar los datos extraídos en un archivo CSV
            save_to_csv(extracted_data)


if __name__ == "__main__":
    main()

Sugerencias de proxy para scrapear Amazon a través de Python

Para la extracción ininterrumpida de datos se dispone de diferentes soluciones de proxy, incluidos proxies IPv4 de centros de datos, móviles rotativos, ISP y residenciales. La lógica de rotación y los agentes de usuario adecuados se utilizan para simular el comportamiento real de los usuarios, mientras que los proxies especiales soportan el scraping a gran escala con rotación interna y amplios grupos de IP. Comprender los pros y los contras de cada opción de proxy es crucial para la extracción ininterrumpida de datos.

Tipo Ventajas Contras
Proxies de centros de datos

Alta velocidad y rendimiento.

Rentabilidad.

Ideal para solicitudes de gran volumen.

Puede ser fácilmente detectado y puesto en la lista negra.

No es fiable contra sistemas anti-scraping o anti-bot.

Apoderados residenciales

Alta legitimidad debido a IPs residenciales reales.

Amplia disponibilidad global de IP para el raspado de datos específicos de la ubicación.

Capacidad de rotación de IP.

Más caros que los proxies de los centros de datos.

Proxies móviles

IPs muy legítimas.

Eficaz para evitar bloqueos y avisos de verificación.

Más caro que otros tipos de proxy.

Más lentos que los proxies de centros de datos debido a la dependencia de la red móvil.

Proxies ISP

IPs de alta fiabilidad.

Más rápidas que las IPs residenciales.

Disponibilidad de IP limitada.

Rotación de IP no disponible.

El scraping de datos de productos de Amazon implica una preparación meticulosa para sortear eficazmente los mecanismos anti-scraping de la plataforma. La utilización de servidores proxy junto con Python permite un procesamiento eficaz de los datos y la extracción selectiva de la información necesaria. A la hora de seleccionar proxies para el web scraping, es fundamental tener en cuenta factores como el rendimiento, el coste, la fiabilidad del servidor y los requisitos específicos del proyecto. El empleo de proxies dinámicos y la aplicación de estrategias para contrarrestar las medidas de seguridad pueden minimizar el riesgo de ser bloqueado y mejorar la eficacia general del proceso de raspado.

Comentarios:

0 Comentarios