Implementa un cazador de ofertas con IA

Vistas: 1
0:00 / 0:00
Implementa un cazador de ofertas con IA

Me apasiona automatizar. No lo puedo evitar. Siempre he pensado que el tiempo es nuestro recurso más valioso y que cualquier tarea repetitiva que tengamos que hacer delante de una pantalla debería ser delegada inmediatamente a una máquina. La vida es demasiado corta como para pasar horas copiando y pegando datos de una web a otra, o abriendo las mismas pestañas todos los días para comprobar si ha bajado de precio ese producto que tanto ansiamos.

El dilema de la información y la ausencia de APIs

En un mundo ideal, cada plataforma web, tienda online y base de datos de internet nos ofrecería una API limpia, estructurada, documentada y gratuita para que nos conectáramos y descargáramos la información directamente. Si quiero saber el menú semanal de un restaurante, o el stock de un componente electrónico en mi distribuidor de confianza, o el precio de unas zapatillas de running, lo lógico sería consultar un endpoint y obtener un bonito archivo estructurado en cuestión de milisegundos.

Pero la realidad de internet es muy diferente. La mayoría de las empresas no ofrecen APIs públicas. Algunas porque no tienen la capacidad técnica de mantenerlas, otras porque prefieren que pases por su portada para mostrarte publicidad, y muchas simplemente por puro desinterés. Cuando no tienes esa API que te conecte de forma directa con la información, la única opción que te queda para evitar el trabajo manual es recurrir al web scraping.

¿Qué es el Web Scraping y por qué nos hace la vida más fácil?

El web scraping es, básicamente, el arte de extraer información de una página web emulando el comportamiento de un navegador web pero de forma automatizada. En lugar de ser tú quien abre el navegador, se desplaza por la página y copia el precio en una libreta, es un programa de software el que realiza estas peticiones, lee el código fuente de la página, extrae los datos que le interesan y los guarda en un formato estructurado como una base de datos, un archivo CSV o un JSON.

Las utilidades prácticas de esto son infinitas. Por ejemplo, en mi caso particular, hay un hábito que repito de forma matemática: cada ochocientos kilómetros cambio mis zapatillas de correr. Mis articulaciones me lo agradecen enormemente. Esto se traduce en que cada tres o cuatro meses me toca rastrear internet buscando el modelo exacto que utilizo en cinco o seis tiendas online de deportes distintas para ver cuál ofrece el precio más competitivo en ese momento. Hacer esto a mano es aburrido y consume un tiempo precioso. Si logro automatizar este rastreo con un script que se ejecute en mi servidor doméstico, habré ganado en calidad de vida.


El talón de Aquiles del Scraping Tradicional

Si llevas algún tiempo en el mundillo de la programación o de la administración de sistemas, es muy probable que hayas oído hablar de herramientas tradicionales para scrapear webs. En el ecosistema de Python, las reinas indiscutibles han sido históricamente librerías como Beautiful Soup, Scrapy o lxml.

Cómo funciona un rastreador clásico (Beautiful Soup y HTML)

El enfoque tradicional es un proceso puramente estructural. Cuando diseñas un scraper clásico, lo primero que haces es descargar el código HTML de la URL objetivo usando una librería de peticiones web como requests. Una vez que tienes ese inmenso documento HTML en memoria, utilizas Beautiful Soup para analizar su estructura.

Para extraer el precio de un portátil, por ejemplo, debes inspeccionar el código fuente de la tienda en tu navegador, buscar el elemento exacto que contiene el precio y analizar sus atributos. A lo mejor descubres que el precio está encerrado en una etiqueta de tipo párrafo con una clase CSS muy específica, algo como class="precio-final". Entonces escribes una línea de código en tu script que dice: búscame todos los elementos de tipo párrafo que tengan la clase precio-final y extrae su texto.

Por qué los selectores CSS se rompen constantemente

Este enfoque funciona espectacularmente bien, es asombrosamente rápido y consume poquísimos recursos de CPU. Sin embargo, tiene un fallo de diseño garrafal: depende por completo de que la estructura de la página web sea inmutable.

En el momento en que el equipo de desarrollo de la tienda online decide rediseñar la web, o simplemente actualiza el framework de diseño que utilizan, toda tu automatización se desmorona. Si cambian la clase precio-final por price-tag, o deciden meter el precio dentro de una tabla en lugar de un párrafo, tu script clásico ya no encontrará nada. De repente, tu automatización silenciosa empieza a fallar, deja de avisarte de las ofertas y te obliga a volver a abrir el editor de código, inspeccionar de nuevo la web, corregir el selector CSS y subir una actualización de tu script. Es un mantenimiento constante y agotador.

Webs dinámicas, tests A/B e internacionalización: La tormenta perfecta

Las dificultades del scraping tradicional no terminan con los cambios de diseño. Hoy en día nos enfrentamos a un ecosistema web sumamente complejo:

  • Identificadores dinámicos: Muchas aplicaciones modernas construidas con React, Angular o Vue generan las clases CSS y los identificadores de los elementos de forma automática y aleatoria en cada compilación del código. Elementos con clases como class="sc-1y8df9-0" que cambian sin previo aviso en cada actualización del portal.
  • Tests A/B: Las grandes tiendas online suelen realizar experimentos continuos. A la mitad de los visitantes les muestran una estructura de página (Diseño A) y a la otra mitad una distinta (Diseño B) para medir cuál convierte mejor las ventas. Si tu scraper clásico se conecta y cae en el Diseño B pero tú lo programaste para el Diseño A, la extracción fallará por completo.
  • Internacionalización: Dependiendo de la IP desde la que se conecte tu script, o de las cabeceras de idioma que envíe, la tienda puede responder con formatos de moneda diferentes, estructuras adaptadas o idiomas distintos, lo cual altera los selectores semánticos que habías definido con tanto esfuerzo.
  • Redes de Distribución de Contenidos (CDNs) y Cloudflare: Estos sistemas actúan como escudos protectores de las webs. Si detectan que un script plano está descargando páginas de forma sistemática y a gran velocidad, bloquean la petición de inmediato mostrando un captcha o una página de error, impidiendo que Beautiful Soup acceda siquiera al código HTML.

La revolución de los Modelos de Lenguaje (LLMs)

Frente a todas estas barreras que hacen del scraping tradicional un dolor de cabeza diario, ha surgido una alternativa revolucionaria gracias al auge de la inteligencia artificial y los modelos de lenguaje locales: el scraping semántico.

Entendimiento semántico vs. Estructura rígida

La gran diferencia de un modelo de lenguaje frente a un parser clásico de HTML como Beautiful Soup es que el LLM no busca una etiqueta exacta ni una clase CSS específica. El LLM es capaz de leer un bloque de texto o un fragmento de código HTML y comprender el contexto de la misma manera que lo haría un ser humano.

Si tú le muestras a una persona el código fuente de una tienda donde aparece la palabra Lenovo ThinkPad X1 Carbon y justo al lado, de cualquier forma maquetada, aparece la cifra 1.299 €, esa persona deducirá inmediatamente que el primer elemento es el nombre del portátil y el segundo es su precio. No necesita saber si el precio está dentro de un contenedor de tipo div o de tipo section. Entiende el significado semántico de las palabras y los números. Eso es exactamente lo que hace un LLM.

Por qué la IA puede interpretar cualquier web como un humano

Al dotar a nuestros scripts de esta capacidad de entendimiento semántico, eliminamos de un plumazo el problema del mantenimiento de los selectores. Ya no importa si la web cambia sus clases CSS todas las semanas, o si los identificadores se generan dinámicamente, o si el diseño varía ligeramente por un test A/B. Mientras el nombre del producto y el precio sigan siendo visibles textualmente en el código de la página, la IA será capaz de localizarlos, relacionarlos y extraérnoslos sin inmutarse.

Podemos utilizar el mismísimo script con el mismo prompt para extraer información de diez tiendas online de tecnología completamente diferentes, con diseños radicalmente distintos, sin tener que escribir ni una sola regla específica de CSS para ninguna de ellas. Esto reduce el coste de desarrollo y el tiempo de mantenimiento prácticamente a cero.

El papel del Open Source y el Self-Hosting con Ollama

Muchos desarrolladores piensan que para hacer esto es obligatorio pasar por caja y contratar APIs de pago de grandes corporaciones como OpenAI o Anthropic. Sin embargo, los entusiastas del software libre y el self-hosting tenemos una herramienta espectacular en nuestras manos: Ollama.

Ollama es una herramienta ligera y sumamente eficiente que nos permite descargar, gestionar y ejecutar modelos de lenguaje de gran tamaño (LLMs) directamente en nuestra propia máquina local, ya sea un ordenador personal, un servidor doméstico en nuestro salón o un VPS en la nube. Todo el procesamiento de datos se realiza de forma local, garantizando nuestra total privacidad, sin depender de conexiones de terceros y, lo más importante de todo, con un coste económico de cero euros por cada consulta realizada. No hay límites de uso ni suscripciones mensuales.


Anatomía de un Scraper con IA: Paso a Paso

Construir un scraper inteligente utilizando Python y Ollama es un proceso sorprendentemente sencillo si se estructuran bien las fases. Aunque pueda parecer que hay magia detrás de la inteligencia artificial, la realidad es que un scraper de IA robusto se fundamenta en cinco pasos de ingeniería de software muy claros y bien definidos.

+-------------+     +------------------+     +------------------------+
|   URL Web   | --> | Petición HTTP    | --> | HTML Crudo (ej. 2 MB)  |
+-------------+     +------------------+     +------------------------+
                                                         |
                                                         v
                                             +------------------------+
                                             | Limpieza BeautifulSoup  |
                                             +------------------------+
                                                         |
                                                         v
+-------------+     +------------------+     +------------------------+
| Ollama (LLM)| <-- | Prompt + HTML    | <-- | HTML Limpio (ej. 20 KB)|
+-------------+     +------------------+     +------------------------+
       |
       v
+-----------------------------+
| JSON Estructurado y Alertas |
+-----------------------------+

Paso 1: La captura del código fuente

El primer paso es el más clásico de todos. Necesitamos obtener el código HTML de la página web que queremos analizar. Para ello, utilizamos la conocida librería requests de Python, que nos permite realizar peticiones HTTP de forma sencilla.

import requests

def descargar_html(url):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }
    response = requests.get(url, headers=headers, timeout=10)
    if response.status_code == 200:
        return response.text
    else:
        raise Exception(f"No se pudo acceder a la web. Código de estado: {response.status_code}")

Al definir unas cabeceras HTTP que imiten a un navegador real (el famoso User-Agent), reducimos la probabilidad de que los servidores sencillos nos bloqueen la entrada pensando que somos un bot básico.

Paso 2: El arte de la limpieza (Reducir el ruido del HTML)

Aquí es donde reside el verdadero secreto de la eficiencia de nuestro scraper con IA. Una página web moderna es inmensa. Cuando descargas el código HTML de una tienda típica como MediaMarkt o Amazon, te encuentras con un archivo de entre 1,5 y 3 Megabytes de tamaño. Este archivo está inundado de miles de líneas de código Javascript, hojas de estilo CSS en línea, menús de navegación global, pies de página, iconos vectoriales en formato SVG y bloques de publicidad.

Si intentamos enviarle este monstruo de código crudo a un modelo de lenguaje que se está ejecutando en la CPU de nuestro servidor local, provocaremos un desastre. El modelo tardará minutos en procesarlo, consumirá gigabytes de memoria RAM y, lo que es peor, se perderá entre tanto ruido técnico y probablemente sufrirá alucinaciones, dándonos resultados incorrectos.

Nuestra misión en Python es realizar una poda drástica y sin piedad de toda esa basura que el LLM no necesita para entender la información. Usando Beautiful Soup, eliminamos todo lo irrelevante de forma quirúrgica:

from bs4 import BeautifulSoup

def limpiar_html(html_crudo):
    soup = BeautifulSoup(html_crudo, "html.parser")

    # Eliminamos elementos que no aportan contenido semántico útil
    for elemento in soup(["script", "style", "nav", "footer", "header", "svg", "noscript", "iframe", "form"]):
        elemento.decompose()

    # Extraemos solo el texto limpio o una estructura HTML muy simplificada
    texto_limpio = soup.get_text(separator=" ")

    # Comprimimos los espacios en blanco repetidos para ahorrar caracteres
    lineas = (linea.strip() for linea in texto_limpio.splitlines())
    bloques = (bloque for bloque in lineas if bloque)
    texto_comprimido = "\n".join(bloques)

    return texto_comprimido

Con este sencillo proceso de limpieza, somos capaces de coger una página web pesadísima de 2 Megabytes y dejarla reducida a un pequeño y delicioso bloque de texto relevante de apenas 15 o 20 Kilobytes. ¡Una reducción de más del noventa por ciento! Ahora el modelo de lenguaje podrá procesar la información en apenas unos segundos sobre nuestra CPU.

Paso 3: Controlando el contexto y los tokens

Cualquier modelo de lenguaje tiene un límite en la cantidad de texto que puede procesar de una sola vez. A esto se le conoce como la ventana de contexto, que se mide en tokens (un token equivale aproximadamente a cuatro caracteres en español).

Incluso después de limpiar el HTML, si nos topamos con una web gigantesca que supera los límites de nuestro modelo local, debemos ser precavidos y truncar el contenido o trocearlo de forma inteligente. Si trabajamos en CPU, reducir el texto al máximo no es solo una cuestión de no superar el límite de contexto del modelo, sino también una estrategia indispensable para mantener unos tiempos de respuesta rápidos y razonables.

Paso 4: Diseñando el prompt ideal y configurando la temperatura a cero

Para que nuestro script funcione de forma automatizada, no queremos que la IA nos responda con un texto amigable o explicaciones educadas como aquí tienes los precios que me has pedido, Lorenzo. Lo que necesitamos es que nos devuelva un formato de datos puramente estructurado que nuestro código de Python pueda interpretar de forma nativa. El formato idóneo para esto es el JSON.

Para lograrlo, debemos redactar un prompt extremadamente claro y estricto. Además, debemos configurar la temperatura del modelo exactamente a cero. La temperatura en los modelos de lenguaje controla la creatividad y la aleatoriedad de las respuestas. Para tareas creativas como escribir un poema o un correo, nos interesa una temperatura alta. Pero para extraer datos de forma exacta, necesitamos que el modelo sea totalmente determinista, es decir, que se ciña de forma estricta a lo que ve en el texto sin inventarse absolutamente nada.

Un prompt que me ha dado resultados fantásticos en mis pruebas es el siguiente:

Extrae el nombre del portátil y su precio actual de la siguiente información web.
Devuelve únicamente un array JSON válido, con la estructura exacta: [{"producto": "Nombre", "precio": 0.0}].
No incluyas explicaciones en texto, no utilices bloques de código Markdown con triple comilla invertida, no saludes ni agregues nada más que el JSON crudo.
Si encuentras características sueltas o especificaciones técnicas sin precio, ignóralas por completo. Concéntrate solo en productos reales con su marca visible (Lenovo, HP, Dell, ASUS).
Extrae un máximo de tres productos.

Información web a procesar:
[AQUÍ INJECTAMOS EL HTML LIMPIO]

Paso 5: El parseo robusto del resultado JSON y las estrategias de contingencia

A pesar de que le pidamos a la IA con total firmeza que solo nos devuelva un JSON crudo, los modelos de lenguaje siguen sin ser programas de lógica pura. A veces, debido a pequeños matices en el procesamiento, el modelo decide envolver el resultado dentro de bloques de código de tipo markdown (con las famosas triples comillas invertidas ```json), o añade un pequeño texto de introducción al principio de la respuesta.

Si nuestro script de Python intenta hacer un json.loads() directo de esa respuesta y se encuentra con caracteres que no pertenecen al JSON, el programa lanzará una excepción y nuestra automatización se romperá. Por tanto, debemos diseñar nuestro parseador para que sea extremadamente tolerante a fallos y cuente con varias estrategias de contingencia en cascada:

  1. Estrategia principal: Intentar cargar la respuesta del modelo directamente usando json.loads(). Si la IA se ha comportado a la perfección, esto funcionará a la primera.
  2. Segunda línea de defensa: Si falla el parseo directo, utilizamos expresiones regulares en Python para buscar cualquier bloque de texto que se encuentre encerrado entre corchetes [...] o llaves {...} y tratamos de parsear únicamente esa sección, descartando cualquier texto introductorio o de cierre que el modelo haya añadido de forma voluntaria.
  3. Tercera línea de defensa: Si todo lo anterior falla, podemos recurrir a limpiadores de cadenas de texto para eliminar los marcadores de bloque de Markdown y reintentar el parseo.

Tener este enfoque de capas de seguridad garantiza que, aunque el LLM tenga un pequeño desliz en el formato de salida, nuestro script sea lo suficientemente inteligente como para extraer el JSON y continuar su ejecución sin detenerse por un error de sintaxis.


Evaluando los Modelos: Velocidad vs. Inteligencia en CPU

Cuando decidimos ejecutar todo este ecosistema en nuestro propio servidor local utilizando Ollama, la elección del modelo de lenguaje que va a procesar nuestras páginas web es una de las decisiones más críticas que debemos tomar. Dependiendo de los recursos de hardware de nuestro equipo, tendremos que encontrar el balance perfecto entre la velocidad de respuesta y la precisión de la extracción.

Mi experiencia en un Slimbook One sin GPU dedicada

Para poner a prueba este sistema de la forma más realista posible, he evitado utilizar mi estación de trabajo principal dotada de una tarjeta gráfica potente. En su lugar, he estado corriendo todas las pruebas de rendimiento en mi Slimbook One, un ordenador compacto y silencioso que tengo en casa configurado como servidor doméstico. Este equipo no cuenta con una tarjeta gráfica dedicada (GPU) ni con unidades de aceleración de inteligencia artificial (NPU). Todo el trabajo pesado de cálculo matemático de los modelos recae de forma exclusiva sobre la CPU.

Esto es un escenario excelente, porque demuestra que cualquier entusiasta que tenga un mini PC de bajo consumo o un servidor doméstico modesto en su hogar puede montar esta misma infraestructura sin tener que invertir miles de euros en hardware especializado.

Llama 3.2 (3B): El rey del equilibrio

El modelo Llama 3.2 de Meta, específicamente en su variante de 3 Billions de parámetros, ha resultado ser el auténtico campeón de mis experimentos para tareas de scraping semántico.

Al ser un modelo sumamente optimizado y con un tamaño muy reducido, es capaz de ejecutarse a una velocidad asombrosa directamente sobre la CPU. En mi Slimbook One, tarda apenas unos pocos segundos en analizar un bloque de HTML limpio de una tienda y devolvernos el JSON estructurado con los productos y sus precios correspondientes. Además, a pesar de su pequeño tamaño físico, su comprensión lectora es excelente. Es capaz de identificar perfectamente las marcas de tecnología más conocidas, descartar los accesorios irrelevantes y asociar de forma impecable cada portátil con su precio de venta correcto.

Qwen 2.5 y Mistral: Potencia a cambio de segundos

Si necesitas realizar tareas de extracción semántica mucho más complejas (por ejemplo, analizar opiniones de clientes en un portal de reservas para determinar el sentimiento del usuario, o clasificar productos de una web en categorías abstractas), los modelos pequeños pueden quedarse un poco cortos de razonamiento. En esos casos, dar el salto a modelos de 7 Billions de parámetros como Qwen 2.5 o Mistral es la solución idónea.

Estos modelos poseen una red neuronal mucho más profunda y rica, lo que les permite comprender matices sutiles y resolver prompts extremadamente complejos de forma sobresaliente. Sin embargo, en un entorno puramente de CPU, este incremento de inteligencia tiene un coste temporal importante. El procesamiento de una sola página web puede pasar de tardar unos pocos segundos a demorarse uno o dos minutos enteros. Si vas a realizar el scraping de forma programada y en segundo plano en tu servidor, quizás la lentitud no sea un problema crítico para ti, pero es un factor muy importante que debes tener en cuenta.

DeepSeek R1 y Phi-3: Pruebas y matices

También he querido poner a prueba otras opciones muy populares de la comunidad:

  • DeepSeek R1 (1.5 Billions): Este modelo de razonamiento destilado destaca por ser asombrosamente rápido sobre la CPU. No consume casi memoria RAM y responde prácticamente al instante. No obstante, para esta tarea concreta de extracción de datos puros y estructuración en JSON, en mis pruebas ha mostrado una tasa de fallos de formato ligeramente superior a la de Llama 3.2. Tiende a añadir explicaciones de razonamiento internas que complican el parseo automatizado.
  • Phi-3 Mini de Microsoft: Una alternativa fantástica y muy ligera que ofrece un comportamiento muy equilibrado. Sigue siendo una opción de primer nivel si buscas un modelo pequeño, rápido y dócil que respete los formatos JSON con bastante fidelidad.

Programación Avanzada en Python para Automatizar

Una vez que tenemos resuelta la lógica de descarga, limpieza y extracción mediante el modelo de inteligencia artificial, es el momento de construir la arquitectura de software que transformará este script conceptual en un sistema de producción robusto y completamente automatizado.

De scripts sencillos a concurrencia y paralelismo

Si queremos monitorizar varias tiendas de informática de forma simultánea, ejecutar el scraping de forma secuencial (tienda por tienda) puede convertirse en un proceso demasiado lento, especialmente si estamos corriendo la IA sobre la CPU.

Para resolver esto, en Python podemos hacer uso de la librería estándar concurrent.futures. Al implementar la concurrencia, nuestro script será capaz de lanzar las peticiones de descarga de las diferentes páginas web de forma paralela. Mientras una tienda está respondiendo a la conexión de red, nuestro script ya está procesando el HTML de otra tienda anterior con el modelo de lenguaje de Ollama. Esto reduce drásticamente el tiempo total de ejecución del programa completo.

import concurrent.futures

def procesar_tienda(url, prompt):
    try:
        html_crudo = descargar_html(url)
        html_limpio = limpiar_html(html_crudo)
        resultado_json = consultar_ollama(html_limpio, prompt)
        return url, resultado_json
    except Exception as e:
        return url, {"error": str(e)}

def ejecutar_rastreo_paralelo(urls, prompt):
    resultados = {}
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        futures = {executor.submit(procesar_tienda, url, prompt): url for url in urls}
        for future in concurrent.futures.as_completed(futures):
            url = futures[future]
            try:
                data = future.result()
                resultados[url] = data
            except Exception as exc:
                resultados[url] = {"error": str(exc)}
    return resultados

Creando un Vigilante de Precios con Historial y Caché

Para que un rastreador de ofertas sea verdaderamente inteligente, no basta con que nos muestre por consola los precios actuales en cada ejecución. El sistema debe tener memoria. Necesitamos almacenar un histórico de los precios extraídos para poder compararlos y saber si realmente se ha producido una bajada de precio interesante.

Podemos implementar un sistema de caché extremadamente sencillo y ligero utilizando archivos de texto plano en formato JSON que almacenen el último estado conocido de cada producto. En cada ejecución de nuestro script:

  1. El programa descarga los precios actuales de la web.
  2. Lee el archivo de caché local para recuperar el precio que tenía el producto en la última consulta realizada.
  3. Compara ambos valores. Si el precio actual es inferior al precio registrado en la caché, se activa una alarma.
  4. Si la bajada de precio es real, actualiza el archivo de caché con el nuevo valor mínimo para evitar enviarnos alertas repetidas innecesariamente.

Integrando alertas automáticas por Telegram

El broche de oro para nuestro vigilante automatizado es lograr que nos avise directamente a nuestro teléfono móvil en el instante en que detecte un chollo. La forma más limpia, cómoda y gratuita de hacer esto en Linux y Python es integrando la API de bots de Telegram.

Crear un bot de Telegram es un proceso sumamente sencillo gracias al asistente BotFather en la propia aplicación. Una vez creado el bot, obtendremos un token de autenticación (un churro largo de caracteres alfanuméricos) y nuestro ID de chat de usuario. Con estos dos parámetros, enviar una notificación instantánea desde Python a nuestro móvil es tan simple como realizar una sola petición HTTP de tipo POST:

def enviar_alerta_telegram(mensaje):
    token_bot = "TU_TELEGRAM_BOT_TOKEN"
    id_chat = "TU_CHAT_ID"
    url = f"https://api.telegram.org/bot{token_bot}/sendMessage"
    payload = {
        "chat_id": id_chat,
        "text": mensaje,
        "parse_mode": "Markdown"
    }
    try:
        response = requests.post(url, json=payload, timeout=10)
        if response.status_code != 200:
            print(f"Error al enviar notificación a Telegram: {response.status_code}")
    except Exception as e:
        print(f"Excepción al conectar con la API de Telegram: {e}")

Imagínate la satisfacción: estás tranquilamente paseando por la calle, tu servidor doméstico ejecuta el script de scraping inteligente en segundo plano, detecta que tu modelo favorito de zapatillas de correr ha bajado un treinta por ciento en una de las tiendas de deportes, y al instante recibes un bonito mensaje en tu Telegram con el enlace directo para realizar la compra. ¡Eso es el verdadero cacharreo útil!


Evitando los muros del Anti-Scraping

Cuando empiezas a jugar con el scraping de forma continua, tarde o temprano te vas a topar con sistemas de seguridad avanzados que intentarán detener la actividad de tus scripts automáticos. Las páginas web de las multinacionales cuentan con herramientas potentes de detección de bots que analizan el comportamiento de cada petición entrante.

La detección de agentes de usuario (User-Agents)

La primera línea de defensa de los servidores web es el análisis de las cabeceras HTTP de la petición, especialmente la cabecera llamada User-Agent. Si realizas una petición directa con la librería requests de Python sin definir esta cabecera, la librería enviará por defecto una firma del tipo python-requests/2.31.0.

Los servidores de seguridad bloquean esta firma de forma fulminante porque revela de manera evidente que la conexión no la está realizando una persona real sentada delante de un navegador web, sino un script automatizado. Para saltarnos esta primera barrera rudimentaria, es absolutamente indispensable imitar las cabeceras de un navegador moderno y popular, como Google Chrome o Mozilla Firefox, tal y como hemos visto en el bloque de código de la sección anterior.

Simulación de comportamiento humano con navegadores reales (Playwright)

Hay portales web sumamente complejos que no se limitan a analizar las cabeceras HTTP. Páginas web modernas construidas enteramente sobre frameworks de Javascript (las conocidas como Single Page Applications o SPAs) no cargan el contenido real de los productos directamente en el HTML que se descarga el servidor. En su lugar, el servidor responde con un documento HTML prácticamente vacío con un script que se ejecuta en el navegador del cliente y es este script el que se encarga de descargar y renderizar la información de los productos de forma dinámica.

Si intentamos scrapear estas webs dinámicas usando únicamente la librería requests de Python, nos descargaremos un cascarón vacío de código sin precios ni nombres de portátiles que nuestra IA no podrá procesar de ninguna manera.

Para solucionar este inconveniente, debemos recurrir a herramientas de simulación de navegadores como Playwright o Selenium. Estas librerías nos permiten arrancar una instancia invisible de un navegador web real (como Chromium o Firefox) en nuestro servidor, dejar que la página cargue por completo, ejecute todos sus scripts de Javascript internos de forma automática, y una vez que el HTML esté completamente renderizado y visible en pantalla, capturar ese código fuente final para enviárselo a nuestro LLM local.

from playwright.sync_api import sync_playwright

def descargar_html_dinamico(url):
    with sync_playwright() as p:
        # Arrancamos un navegador invisible
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url, wait_until="networkidle") # Esperamos a que la red se calme
        html_completo = page.content() # Capturamos el HTML ya renderizado por JS
        browser.close()
        return html_completo

Rotación de Proxies e IPs: Cuándo es necesario dar el salto

Si tu intención es rastrear decenas de miles de páginas web todos los días para realizar un estudio de mercado a gran escala, hacer todas las peticiones desde la conexión de internet de tu casa o desde la IP fija de tu servidor VPS provocará que los firewalls de seguridad bloqueen tu dirección IP de forma permanente.

Para proyectos profesionales o de gran envergadura, se vuelve indispensable implementar técnicas de rotación. Esto consiste en configurar nuestro script de Python para que desvíe cada petición HTTP a través de un servidor proxy intermedio diferente, de forma que el servidor final de la tienda online vea llegar las conexiones desde miles de direcciones IP geográficamente distribuidas por todo el mundo, imposibilitando que puedan bloquear nuestro rastreador de ofertas.


Casos de Uso que te Cambiarán el Día a Día

El web scraping semántico con inteligencia artificial local abre un abanico gigantesco de posibilidades que antes estaban reservadas únicamente a desarrolladores expertos con amplios conocimientos de programación web y selectores CSS complejos. Ahora, cualquier entusiasta de la informática puede dar vida a proyectos increíbles.

Seguimiento inteligente de ofertas en Black Friday

Durante las campañas de rebajas como el Black Friday o el Cyber Monday, muchas tiendas juegan con los precios de forma constante, subiéndolos días antes para luego simular un descuento espectacular.

Con tu vigilante de ofertas con IA local, puedes empezar a rastrear los portátiles o componentes que te interesan meses antes del evento. Al guardar todos los precios diarios en tu base de datos o archivo de caché local, podrás comprobar de forma científica si la oferta anunciada el día del Black Friday es un chollo real o un burdo engaño comercial. No hay mejor escudo contra el consumismo impulsivo que contar con datos reales y precisos.

Control de Stock para componentes difíciles de conseguir

¿Intentando conseguir stock de una tarjeta gráfica de última generación, de una consola retro muy cotizada o de entradas para el concierto de tu grupo favorito que se agotan en minutos?

En lugar de pasarte el día entero pulsando la tecla de refrescar en tu navegador, puedes programar a tu vigilante inteligente para que realice la inspección de la web de venta cada cinco minutos. En el momento en que el modelo de lenguaje analice la web y deje de ver el texto sin stock o agotado y encuentre un precio de venta activo, te enviará un zambombazo inmediato a tu Telegram con el enlace de compra directa para que seas el primero en adquirir el artículo.

Recetas de cocina y planificadores semanales a medida

Otro escenario sumamente interesante es el de la organización del hogar. Puedes programar un script de scraping con IA para que visite de forma periódica tus blogs de cocina favoritos y extraiga de forma estructurada todas sus nuevas recetas: ingredientes, tiempos de preparación y pasos de elaboración.

Al transformar esas recetas en formato JSON limpio de forma totalmente automática gracias a la IA, puedes alimentar un gestor de recetas personal en tu propio servidor doméstico, o incluso diseñar un asistente inteligente que analice los ingredientes que tienes en tu nevera y te sugiera un menú semanal equilibrado seleccionando recetas de tu base de datos de scraping de forma totalmente autónoma.


Conclusiones: El poder del cacharreo democratizado

Hemos vivido una de las mayores revoluciones tecnológicas en el mundo del desarrollo de software gracias a la madurez de los modelos de lenguaje de código abierto y herramientas como Ollama. El web scraping, que tradicionalmente requería un mantenimiento continuo y unos conocimientos técnicos profundos sobre la estructura interna de la web, se ha convertido ahora en una disciplina accesible, divertida y resiliente para cualquier persona con ganas de experimentar y cacharrear.

Montar tu propio cazador de ofertas semántico en local, sin gastar dinero en APIs externas y controlando tus datos al cien por cien es un proyecto sumamente enriquecedor que te permitirá ahorrar dinero en tus compras diarias y te abrirá un abanico de infinitas posibilidades de automatización en tu servidor doméstico. El único límite es tu propia imaginación. ¡Te animo a que te pongas a escribir tu primer script de scraping inteligente hoy mismo y empieces a pasártelo en grande automatizando tu día a día!


Deja una respuesta