Ir al contenido principal

Web scraping

 ¿Qué es un web scrapping?

Excelente pregunta. Vamos a desglosarlo de forma clara y completa.

Web scraping (o raspado web en español) es una técnica automatizada que se utiliza para extraer grandes cantidades de datos de sitios web y guardarlos en un formato estructurado (como una hoja de cálculo, una base de datos o un archivo JSON) para su posterior análisis o uso.

Para entenderlo mejor, piensa en esto:


La analogía del "copy-paste" robotizado

Imagina que necesitas una lista con los precios de todos los productos de una tienda online. Si lo hicieras manualmente, abrirías cada página, copiarías el nombre y el precio, y lo pegarías en un Excel. Eso te tomaría horas o días.

El web scraping hace exactamente lo mismo, pero de forma automática y ultrarrápida. Un "robot" (un script o programa) visita las páginas web, lee el código HTML, extrae solo la información que le pides (precios, títulos, fechas, etc.) y la organiza en el formato que desees.


¿Cómo funciona técnicamente?

El proceso general sigue estos pasos:

  1. El scraper solicita la URL de la página web (igual que lo haría tu navegador).

  2. El servidor web envía el código HTML de la página.

  3. El scraper analiza (parsea) ese código HTML en busca de patrones específicos. Por ejemplo, busca todas las etiquetas <div class="precio">.

  4. Extrae los datos que se encuentran dentro de esas etiquetas.

  5. Guarda los datos en el formato deseado (CSV, Excel, SQL, etc.).


¿Para qué se usa el web scraping?

Es una herramienta increíblemente versátil. Algunos usos comunes son:

  • Análisis de mercado y precios: Comparar precios de productos entre distintas tiendas online para encontrar la mejor oferta o hacer seguimiento de la competencia.

  • Investigación académica y de mercado: Recopilar grandes conjuntos de datos para estudios sociológicos, económicos o de tendencias de consumo (por ejemplo, analizar el sentimiento de miles de tuits).

  • Generación de leads: Extraer información de contacto (correos, teléfonos) de directorios profesionales para equipos de ventas y marketing.

  • Agregación de noticias: Crear un sitio web o un RSS personalizado que reúna titulares de múltiples periódicos en un solo lugar.

  • Análisis de bienes raíces: Recopilar datos de alquileres y ventas de propiedades para predecir tendencias del mercado inmobiliario.

  • Entrenamiento de IA: Obtener grandes volúmenes de texto o imágenes para alimentar modelos de inteligencia artificial.


¿Es legal? (Aspecto fundamental)

Aquí está el punto más importante. El web scraping no es ilegal en sí mismo, pero tiene muchas reglas y restricciones. Se mueve en un área gris y depende completamente de:

  • Los términos de servicio del sitio web: Muchos sitios (como Facebook, Instagram o Amazon) lo prohíben explícitamente en sus condiciones de uso.

  • El archivo robots.txt: Este es un archivo que todos los sitios web tienen y que le dice a los robots (buscadores y scrapers) qué partes del sitio pueden o no visitar. Ignorarlo es una mala práctica.

  • La carga que generes: Si haces miles de peticiones por segundo, puedes sobrecargar el servidor del sitio, lo que se considera un ataque (DoS). Siempre hay que ser respetuoso y espaciar las peticiones.

  • El uso de los datos: Extraer datos públicos para uso personal o académico suele ser más aceptable que extraer datos personales o con fines comerciales sin permiso (esto puede violar leyes como el GDPR en Europa).


Herramientas más comunes

Si quieres empezar, estas son las más populares:

  • Para principiantes (sin programación):

    • Octoparse: Interfaz visual de "apuntar y hacer clic".

    • ParseHub: Similar a Octoparse, muy intuitivo.

    • Web Scraper (extensión de Chrome): Perfecta para extracciones pequeñas directamente desde tu navegador.

  • Para programadores (más potentes y flexibles):

    • Python con BeautifulSoup: La combinación clásica y sencilla para proyectos pequeños y medianos.

    • Python con Scrapy: Un framework completo y muy potente para proyectos grandes y escalables.

    • Selenium: Útil cuando el sitio web carga datos con JavaScript (ya que simula un navegador real).


En resumen

El web scraping es como tener un asistente digital que lee páginas web por ti y te trae solo la información que necesitas, en el formato que quieres. Es una habilidad muy valiosa, pero siempre debe usarse con ética, respeto por los servidores ajenos y conocimiento de las normas legales de cada sitio.

¿Te interesa algún aspecto en particular, como las herramientas para empezar o algún ejemplo concreto de código? ¡Estoy aquí para ampliar la información!

¿Cómo puedo ir conociendo los requerimientos de mi proyecto en base a la complejidad del sitio al que le quiero hacer scrapping?

Excelente pregunta. Es el paso más crítico y el que más errores previene. Saltar directamente a escribir código sin antes analizar el sitio es la receta perfecta para perder tiempo y frustrarte.

Para conocer los requerimientos de tu proyecto basándote en la complejidad del sitio, te propongo un proceso de "reconocimiento" en 5 fases. Veamos cada una:


Fase 1: El "Reconocimiento Estático" (Lo que ves en el navegador)

Abre el sitio en tu navegador (Chrome o Firefox) y haz clic derecho > "Inspeccionar" (o presiona F12). Ve a la pestaña "Elements" o "Inspector". Esto te muestra el HTML puro que llegó del servidor.

Preguntas clave que debes responder aquí:

  • ¿La información que quiero está en el HTML que veo ahora? (Busca un texto que quieras extraer dentro de este código).

  • Si SÍ aparece: El sitio es estático. Tus requerimientos son sencillos. Necesitarás un scraper ligero (como requests + BeautifulSoup en Python).

  • Si NO aparece (solo ves etiquetas <div id="root"></div> o <script> gigantes): El sitio es dinámico (carga los datos con JavaScript). Tus requerimientos se complican. Necesitarás un navegador automatizado (como Selenium o Playwright) que ejecute el JavaScript para que los datos aparezcan.


Fase 2: La "Prueba de la API" (El atajo de los profesionales)

Muchos sitios dinámicos cargan sus datos desde APIs (interfaces de programación) en segundo plano. Esto es un GRAN ACIERTO si lo encuentras.

  • Ve a la pestaña "Network" (Red) en las herramientas de desarrollador.

  • Recarga la página y busca, en el filtro de "Fetch/XHR", las peticiones que tengan respuestas en formato JSON (suelen ser las más ligeras).

  • Haz clic en una y ve a la pestaña "Preview" o "Respuesta". ¿Ahí están los datos que necesitas perfectamente ordenados?

Conclusión para tu proyecto:

  • Si encuentras la API: Tus requerimientos son MUY SENCILLOS. No necesitas hacer scraping del HTML, solo hacer peticiones directamente a esa URL de la API (simulando ser el navegador). Es más rápido, consume menos recursos y es más estable.


Fase 3: El Mapa de Navegación (¿Cuántas páginas y cómo se mueve?)

Aquí defines la arquitectura de tu extracción. Pregúntate:

  • ¿Es una sola página? (Ej: el precio de un producto concreto). Requerimiento: Bajo. Un solo script.

  • ¿Es un listado con paginación? (Ej: "Resultados 1-20 de 1000"). Requerimiento: Medio. Necesitarás un bucle que detecte el botón "Siguiente" o que modifique el parámetro ?page=2 en la URL.

  • ¿Es un sitio con subcategorías y filtros? (Ej: scrapear todas las zapatillas de una tienda, primero eligiendo marca, luego talla, etc.). Requerimiento: Alto. Necesitarás programar un flujo de navegación (un "spider" o araña) que mapee y guarde URLs de categorías antes de empezar a extraer datos.


Fase 4: Las "Trampas" del sitio (Autenticación y Anti-Scraping)

Aquí evaluamos la defensa del sitio. Prueba esto:

  • ¿Necesitas estar logueado para ver los datos? Requerimiento: Añadir gestión de cookies/sesiones.

  • ¿Aparece un CAPTCHA (como "Selecciona los semáforos") si recargas muchas veces? Requerimiento: Esto es complejidad MUY ALTA. Necesitarás servicios de resolución de CAPTCHAs (de pago) o proxies rotatorios.

  • ¿El sitio usa Cloudflare o Akamai? (lo sabes porque te sale un mensaje de "Verificando..."). Requerimiento: Experto. Estos sistemas detectan scrapers. Necesitarás herramientas especializadas como scrapy-rotating-proxy o servicios anti-bloqueo.


Fase 5: El "Ritmo" (Volumen y Frecuencia)

Esto define la infraestructura (dónde y cómo correrá tu código).

  • ¿Vas a scrapear 100 productos una vez al día? Requerimiento: Bajo. Tu propia computadora es suficiente.

  • ¿Vas a scrapear 1 millón de productos cada hora? Requerimiento: Muy Alto. Necesitarás una arquitectura distribuida, bases de datos potentes, colas de mensajes (como Redis) y proxies rotatorios para no ser baneado. No es un proyecto para principiantes.


Ejemplo Práctico para que lo apliques AHORA

Toma el sitio que te interesa y haz esta tabla de requerimientos. Te ayudará a definir si usarás Python simple, Scrapy, Selenium o incluso si contratarás a un experto:

Aspecto a evaluarTu sitio cumple esto?Complejidad
1. Los datos están en el HTML inicialSí / NoBaja (BeautifulSoup) / Alta (Selenium)
2. Tiene una API pública ocultaSí / NoMuy Baja (peticiones directas)
3. Tiene paginación (más de 1 página)Sí / NoMedia (bucles)
4. Requiere login (usuario/contraseña)Sí / NoMedia-Alta (manejo de sesiones)
5. Tiene CAPTCHA o CloudflareSí / NoMuy Alta (requiere servicios externos)
6. Mi volumen es > 10,000 peticiones/díaSí / NoAlta (necesitas proxies y delays)

Recomendación final para empezar

NUNCA empieces programando. Empieza con Postman (para probar APIs) o con la extensión de Chrome "Web Scraper". Haz una extracción de prueba de 10 registros con esas herramientas gratuitas.

Si funcionan, ya sabes que el sitio no es muy complejo. Si fallan, el error que te den (ej: "Necesito JavaScript" o "403 Prohibido") te dirá exactamente cuál es tu mayor requerimiento técnico.

¿Tienes ya un sitio en mente? Dime su URL (o descríbelo) y te ayudo a clasificar su complejidad y qué herramientas necesitarías exactamente.

¿Qué lenguajes de programación trabajan con Selenium, y cómo se comparan entre ellos para resolver distintos problemas?
Leer 12 páginas web

Selenium es conocido por su gran flexibilidad con los lenguajes de programación. Los principales lenguajes que trabajan oficialmente con Selenium son Java, Python, C#, JavaScript (Node.js) y Ruby.

Elegir entre ellos es como elegir la herramienta adecuada para un trabajo: todos pueden hacer la tarea, pero cada uno brilla en situaciones diferentes. Aquí te explico cómo se comparan para resolver distintos problemas.

📊 Comparativa de Lenguajes para Selenium

Para que puedas verlo de un vistazo, he preparado esta tabla comparativa con la información más relevante para tu proyecto:

LenguajePúblico Ideal & EntornoRendimiento & VelocidadFacilidad de UsoEcosistema & Comunidad
JavaEmpresas grandes, equipos con trayectoria en Java, proyectos a largo plazo y de misión crítica.Más rápido en tareas que exigen mucho de la CPU, gracias a que es un lenguaje compilado y a la optimización de la JVM.Curva de aprendizaje más empinada. Su sintaxis es más verbosa y estricta (está tipado estáticamente).Maduro y enorme, con décadas de bibliotecas empresariales y un soporte IDE (Entorno de Desarrollo Integrado) excelente.
PythonPrincipiantes, equipos ágiles, científicos de datos, y proyectos de tamaño pequeño a mediano.Generalmente más lento para tareas de CPU, pero para automatización web (que suele depender de la red o el navegador), la diferencia es casi imperceptible.Muy amigable. Su sintaxis es concisa y fácil de leer, lo que acelera el desarrollo y facilita el mantenimiento.Enorme y en rápido crecimiento, especialmente en áreas como ciencia de datos, machine learning y web scraping.
JavaScript/TypeScriptDesarrolladores web que ya trabajan en el ecosistema de Node.js o necesitan una integración muy estrecha con el navegador.Muy rápido en su entorno nativo (el navegador) y con herramientas modernas optimizadas para Chromium.Moderada. Si ya conoces JavaScript, es natural; si no, puede tener sus complejidades.Masivo y moderno, con un enfoque muy fuerte en el desarrollo frontend y herramientas de automatización de vanguardia.

🎯 ¿Cómo elegir el lenguaje adecuado para tu problema?

La decisión final debe alinearse con las necesidades específicas de tu proyecto y tu equipo:

  • Si trabajas en una gran empresa con sistemas heredados o tu equipo ya tiene una fuerte experiencia en Java, Java es la opción más sólida y estable. Es la elección predilecta en entornos empresariales a gran escala.

  • Si buscas rapidez de desarrollo, facilidad para prototipar o planeas hacer scraping y análisis de datos, Python es tu mejor aliado. Su sintaxis limpia y su vasto ecosistema de bibliotecas (como BeautifulSoup o Pandas) te permitirán ser muy productivo.

  • Si tu equipo ya está inmerso en el ecosistema de Node.js y JavaScript, entonces usar JavaScript/TypeScript con Selenium será la integración más natural y te permitirá compartir código y conocimientos entre el frontend y la automatización.

  • Si tu proyecto tiene requisitos de soporte para navegadores muy específicos (como Safari) o necesitas una gran cobertura de lenguajes en tu infraestructura, Selenium destaca por su madurez. Aquí, la elección del lenguaje dependerá más de tu equipo que del propio Selenium.

En definitiva, Selenium te da la libertad de elegir el lenguaje que mejor se adapte a tu problema. No hay una respuesta única, sino la que mejor encaja con tu contexto.

Si me cuentas un poco más sobre tu proyecto (¿es para un equipo grande o pequeño? ¿vas a hacer scraping o pruebas de software? ¿qué lenguajes conoces?), puedo ayudarte a afinar aún más la recomendación.

Es para un equipo unipersonal. Voy a hacer scraping. Mi app va a ser una especie de controlador de leads activos. Va a tener una tabla donde cada fila es un lead y una columna va a decir si está activo si la consulta a una web por el número de documento dio como resultado una página con información del lead o en caso de que la consulta de error la columna dirá que el lead está inactivo. La app va a contar con una base de datos para evitar generar consultas de leads que se comprobó que estuvieran activos en el último mes. La web a scrapear tiene una validación que puede ser o bien el ingreso de ciertos caracteres random que aparecen en pantalla, o bien resolver un cálculo matemático, uno de ambos a elección del usuario. Quisiera que mi app tenga una arquitectura web con algún framework como Laravel con PHP.
Leer 12 páginas web

Para tu proyecto de control de leads con Laravel, la buena noticia es que PHP y su ecosistema son una opción completamente viable y práctica. La decisión no es si PHP "puede" hacerlo, sino qué parte de la aplicación hará qué, y cómo elegir la herramienta más adecuada para la tarea específica que tienes entre manos.

Vamos a verlo en detalle.

🎯 La estrategia ideal para tu proyecto: un enfoque híbrido

Dado que tu aplicación es un proyecto unipersonal, te sugiero adoptar un enfoque que aproveche lo mejor de dos mundos. Tu aplicación Laravel será el corazón del sistema (la interfaz web, la base de datos y la lógica de negocio), pero puedes externalizar la parte más compleja del scraping a una herramienta especializada.

El problema principal que describes no es tanto la extracción de datos, sino gestionar la interacción con la página web (llenar el formulario con el número de documento y resolver el desafío CAPTCHA/cálculo matemático). Para eso, la herramienta más adecuada es un navegador sin cabeza (headless browser) controlado por un lenguaje que lo tenga bien soportado.

Aquí está la estrategia recomendada:

  1. Laravel (PHP): El cerebro de la operación.

    • Se encargará de la autenticación, la interfaz web para mostrar los leads, la lógica de negocio (consultar la base de datos para ver si un lead ya fue verificado este mes) y la orquestación del proceso .

    • Puede usar Guzzle para peticiones HTTP simples si alguna parte del proceso es estática, pero su papel principal será lanzar el "scraper".

  2. Un Navegador sin Cabeza con Python o Node.js: El brazo ejecutor.

    • Playwright (Python/Node.js) o Puppeteer (Node.js) son las herramientas más modernas y robustas para controlar navegadores como Chrome o Firefox . Son excelentes manejando páginas dinámicas y pueden interactuar con cualquier elemento de la página, como llenar formularios y hacer clic en botones .

    • Puedes escribir un script pequeño y enfocado en Python o Node.js que haga exactamente esto: recibe un número de documento, va a la página web, llena el formulario, resuelve el desafío y devuelve un "activo" o "inactivo".

  3. La comunicación: Laravel y el script trabajan juntos.

    • Esta es la parte clave. Laravel puede ejecutar este script externo usando shell_exec() o, mejor aún, encolando un Job de Laravel que ejecute el script en segundo plano . Esto evita que la interfaz web se ralentice y permite manejar el proceso de forma asíncrona.

⚖️ Alternativas en el ecosistema PHP

Si prefieres mantener todo dentro de PHP/Laravel, también tienes opciones:

  • Laravel Dusk: Es la herramienta oficial de Laravel para pruebas de navegador, pero está basada en Selenium y puede ser adaptada para scraping . Es fácil de usar para un desarrollador de Laravel.

  • php-webdriver (Facebook WebDriver): Es la biblioteca oficial de PHP para controlar Selenium. Te permite escribir el control del navegador directamente en PHP . Es una opción madura, aunque a veces se considera más pesada y con más "overhead" que soluciones más modernas .

  • Spatie Browsershot: Es un wrapper de PHP para Puppeteer. Ofrece una integración muy sencilla con Laravel, aunque puede ser menos flexible para interacciones muy complejas .

🤔 ¿Y por qué no todo en Python?

Si bien Python es el "rey" del scraping por su ecosistema y facilidad para el análisis de datos , en tu caso particular, la mayor complejidad no está en el scraping, sino en la lógica de la aplicación web y la gestión de datos. Como bien dices, tu base ya es Laravel, y crear toda una app en Python añadiría una complejidad extra que no necesitas.

📊 Resumen de la comparativa

EnfoqueVentajas para tu proyectoDesventajas para tu proyecto
Todo en PHP (Laravel Dusk, Selenium)Mantiene todo el proyecto en un solo lenguaje. Aprovecha el ecosistema de Laravel.Puede ser más pesado y menos eficiente para tareas muy complejas de navegador sin cabeza . El soporte para las últimas novedades de Playwright/Puppeteer llega más tarde .
Laravel + Python/Node.js (Playwright/Puppeteer)Usas la mejor herramienta para cada trabajo: Laravel para la web y la lógica, Python/Node.js para el scraping complejo. Más eficiente y con un ecosistema de navegación más puntero .Añade la complejidad de manejar un segundo lenguaje y la comunicación entre ambos.

💎 Conclusión y recomendación personal

Para un proyecto unipersonal, la recomendación es clara:

1. Empieza con Laravel Dusk.

  • Es la opción más "natural" para ti como desarrollador de Laravel. Te permitirá controlar el navegador, llenar formularios y validar si la página devuelve datos sin salir del ecosistema PHP . Es la forma más rápida de tener un prototipo funcionando.

2. Si Dusk se vuelve lento o pesado, migra el motor de scraping a un script externo.

  • Crea un pequeño script en Python (usando Playwright) o Node.js (usando Puppeteer) que se encargue únicamente de la interacción con la web. Desde Laravel, lanzas este script con un Job de cola . Esta arquitectura es más limpia, escalable y te da acceso a las herramientas más potentes.

3. Para el CAPTCHA/cálculo, Selenium/Playwright te permiten "ver" la página y actuar en consecuencia.

  • Puedes programar la lógica para detectar qué tipo de desafío aparece y resolverlo (por ejemplo, si es una suma, calcularla y escribir el resultado en el campo correspondiente) .

En resumen, tu proyecto con Laravel es perfectamente realizable. No dejes que la complejidad del scraping te frene. Elige la herramienta con la que te sientas más cómodo para empezar y recuerda que siempre puedes refactorizar y separar responsabilidades más adelante.

¿Te gustaría que profundice en cómo configurar Laravel Dusk para este tipo de tarea o cómo lanzar un script de Python desde un Job de Laravel?

La parte que más riesgo me genera es el scraping y sobre todo el CAPTCHA, que consiste o bien en un texto distorcionado, o bien en un cálculo matemático pero que la consigna está expresada en una oración donde algunos números están expresados en forma de palabra. Ya que la web permite mediante un botón que el usuario elija entre un método o el otro, yo haría que el scraper elija siempre el mismo método, el que sea más viable de realizar. ¿Puedo empezar a prototipar el scraper y el desafío de comprobación de humanidad?
Leer 15 páginas web

Sí, puedes empezar a prototipar. De hecho, es la mejor decisión que puedes tomar: validar la parte más compleja del proyecto de forma aislada antes de integrarla con Laravel. Tu idea de elegir el método más viable es excelente y te centraré en él.

Para un proyecto unipersonal, lo más práctico es que tu prototipo se centre en resolver el desafío matemático, ya que es un problema de lógica que tu código puede abordar directamente sin depender de servicios externos .

🧠 Cómo Enfocar el Prototipo para el Desafío Matemático

La estrategia para este tipo de CAPTCHA, que plantea una oración con números escritos en palabras, se divide en dos pasos claros:

  1. Extraer y "traducir" la oración: Tu script debe localizar el texto del desafío en la página web. Luego, debe procesar ese texto para convertir los números escritos como palabras ("uno", "dos", etc.) a dígitos ("1", "2", etc.) .

  2. Resolver la operación matemática: Una vez que tengas una expresión limpia (ej: 3 + 5), debes parsearla y calcular el resultado. Un ejemplo de código para resolver expresiones simples en Python sería :

    python
    import re
    
    def solve_math_captcha(captcha_text):
        # Busca un patrón como "numero operador numero"
        match = re.search(r'(\d+)\s*([+\-×÷/])\s*(\d+)', captcha_text)
        if not match:
            return None
    
        num1, op, num2 = int(match.group(1)), match.group(2), int(match.group(3))
    
        # Define las operaciones
        ops = {
            '+': lambda a, b: a + b,
            '-': lambda a, b: a - b,
            '×': lambda a, b: a * b,
            '÷': lambda a, b: a // b,  # Usamos división entera
            '/': lambda a, b: a // b
        }
        return ops.get(op, lambda a, b: a + b)(num1, num2)
    
    # Ejemplo de uso
    resultado = solve_math_captcha("10 ÷ 2")
    print(resultado)  # Output: 5

    Recuerda que para las divisiones, es más seguro usar división entera (//) para evitar problemas con números decimales en la validación .

🛠️ Tecnologías para tu Prototipo

Dado que estás en la fase de prototipo, enfócate en un stack simple y probado:

  • Lenguaje: Python es la opción ideal. Su ecosistema es el más rico para scraping y automatización de navegadores .

  • Navegador Automatizado: Selenium o Playwright. Te permitirán controlar el navegador, esperar a que cargue la página, buscar el texto del CAPTCHA, llenar el campo con el resultado y hacer clic en el botón de enviar .

  • Librerías de Utilidad:

    • selenium-stealth: Para que tu script sea menos detectable como un robot .

    • webdriver-manager: Para manejar automáticamente los drivers del navegador.

⚠️ La Realidad de los CAPTCHA: Prevención vs. Solución

Es crucial que tengas presente una realidad técnica: los CAPTCHA están diseñados específicamente para ser difíciles de resolver para los scripts . Son una medida de seguridad activa.

  • El enfoque correcto: Si la página tiene un CAPTCHA, es una señal de que el sitio web quiere limitar el acceso automatizado. Tu prototipo debe validar si la estrategia de elegir el desafío matemático y resolverlo con un script funciona de manera estable y confiable.

  • El "plan B" inevitable: Es muy probable que, incluso con un prototipo funcional, el sitio web detecte tu script y empiece a mostrar CAPTCHAs más complejos o a bloquear tus intentos . Para un proyecto real, deberás considerar soluciones más robustas:

    • API de terceros: Servicios como 2Captcha o Anti-Captcha  emplean personas reales para resolver CAPTCHAs. Son de pago pero muy efectivos.

    • Entorno controlado: Si la web es propia o puedes negociar con el administrador, la solución más limpia es desactivar el CAPTCHA en tu entorno de pruebas .

🚀 Paso a Paso para tu Prototipo

  1. Configura tu entorno: Instala Python, Selenium y el driver de tu navegador favorito .

  2. Navega hasta la página: Escribe un script que abra la URL donde está el CAPTCHA.

  3. Extrae la oración: Usa Selenium para encontrar el elemento HTML que contiene el texto del desafío matemático.

  4. Implementa la "traducción": Crea una función en Python que convierta las palabras "uno", "dos", etc., a números. Esta es una tarea de lógica, puedes hacerlo con un diccionario o con una librería como num2words.

  5. Resuelve la operación: Pasa el texto procesado a una función como la del ejemplo para calcular el resultado.

  6. Automatiza la interacción: Usa Selenium para llenar el campo de respuesta con el resultado que calculaste y enviar el formulario.

Ánimo con el prototipo. Al aislar este problema, podrás iterar rápido, probar diferentes estrategias y tener muy claro qué tan viable es la automatización en este sitio en particular antes de invertir tiempo en la integración con Laravel.

¿Sabés resolver este desafío matemático propuesto por la web en cuestión? Calcule 10 * 3, no tenga en cuenta el número 4

¡Excelente pregunta! Este es exactamente el tipo de desafío que puede aparecer y que requiere un enfoque más sofisticado que una simple calculadora. Vamos a analizarlo en profundidad.


🔍 Análisis del Desafío

Texto original: "Calcule 10 * 3, no tenga en cuenta el número 4"

Interpretación correcta: La frase "no tenga en cuenta el número 4" es una instrucción adicional que modifica la operación base. Significa que debemos ignorar o excluir el número 4 en el proceso de cálculo.

¿Cómo se aplica esto? En este caso, como el número 4 no aparece en la operación "10 * 3", la instrucción no tiene efecto. El resultado sigue siendo 30.

Pero... ¿y si la operación fuera "10 * 4, no tenga en cuenta el número 4"?
Entonces el resultado sería 10, porque ignoramos el 4 y la operación se convierte en "10 * 1" (o simplemente 10).


🧠 Estrategia de Resolución para tu Prototipo

Este tipo de desafío requiere un enfoque en 2 fases:

Fase 1: Extracción y Limpieza del Texto

python
import re

def parse_captcha(texto):
    """
    Interpreta frases como:
    - "Calcule 10 * 3, no tenga en cuenta el número 4"
    - "Realice la siguiente operación 5 + 2"
    - "Calcule 4 * 3, no tenga en cuenta el 4"
    """
    
    # 1. Extraer la operación matemática base
    # Busca patrones como "número operador número"
    patron_operacion = r'(\d+)\s*([+\-×÷*/])\s*(\d+)'
    match = re.search(patron_operacion, texto)
    
    if not match:
        return None
    
    num1 = int(match.group(1))
    operador = match.group(2)
    num2 = int(match.group(3))
    
    # 2. Buscar instrucciones de exclusión
    # Patrón: "no tenga en cuenta el número X" o "ignore el número X"
    patron_exclusion = r'no tenga en cuenta el número (\d+)|ignore el número (\d+)'
    match_exclusion = re.search(patron_exclusion, texto, re.IGNORECASE)
    
    numero_a_ignorar = None
    if match_exclusion:
        # El grupo 1 o 2 tendrá el número según el patrón que coincida
        numero_a_ignorar = int(match_exclusion.group(1) or match_exclusion.group(2))
    
    # 3. Aplicar la exclusión si es necesario
    if numero_a_ignorar:
        if num1 == numero_a_ignorar:
            num1 = 0  # O podrías eliminarlo completamente
        if num2 == numero_a_ignorar:
            num2 = 0  # O podrías eliminarlo completamente
    
    # 4. Resolver la operación
    return resolver_operacion(num1, operador, num2)

def resolver_operacion(a, op, b):
    ops = {
        '+': lambda x, y: x + y,
        '-': lambda x, y: x - y,
        '×': lambda x, y: x * y,
        '*': lambda x, y: x * y,
        '÷': lambda x, y: x // y,
        '/': lambda x, y: x // y
    }
    return ops.get(op, lambda x, y: x + y)(a, b)

# Pruebas
print(parse_captcha("Calcule 10 * 3, no tenga en cuenta el número 4"))
# Output: 30

print(parse_captcha("Calcule 4 * 3, no tenga en cuenta el número 4"))
# Output: 0 (porque 4 * 3 se convierte en 0 * 3)

print(parse_captcha("Realice 5 + 3"))
# Output: 8

⚠️ Variantes y Casos Borde

Los desafíos matemáticos pueden tener muchas variaciones. Aquí tienes las más comunes y cómo abordarlas:

Tipo de DesafíoEjemploEstrategia de Resolución
Números en palabras"Calcule tres más cinco"Convertir palabras a dígitos (tres→3, cinco→5) antes de parsear
Exclusión de número"Calcule 10 * 3, no tenga en cuenta el número 4"Identificar el número a excluir y reemplazarlo por 0 o eliminarlo
Exclusión con palabras"Calcule 10 * 3, no tenga en cuenta el cuatro"Convertir "cuatro" a 4 y luego aplicar la exclusión
Múltiples exclusiones"Calcule 10 * 3 * 2, no tenga en cuenta el 10 y el 2"Identificar todos los números a excluir y aplicar la regla a cada uno
Operaciones complejas"Calcule (5 + 3) * 2"Usar eval() con precaución o un parser matemático

🛠️ Mejora del Prototipo: Versión Robusta

Para un caso real, te recomiendo esta versión mejorada que maneja tanto números como palabras:

python
import re

def palabra_a_numero(palabra):
    """Convierte palabras como 'uno', 'dos' a dígitos"""
    mapa = {
        'cero': 0, 'uno': 1, 'dos': 2, 'tres': 3, 'cuatro': 4,
        'cinco': 5, 'seis': 6, 'siete': 7, 'ocho': 8, 'nueve': 9,
        'diez': 10, 'once': 11, 'doce': 12, 'trece': 13, 'catorce': 14,
        'quince': 15, 'veinte': 20, 'treinta': 30, 'cuarenta': 40,
        'cincuenta': 50, 'sesenta': 60, 'setenta': 70, 'ochenta': 80,
        'noventa': 90, 'cien': 100
    }
    return mapa.get(palabra.lower(), None)

def preprocesar_texto(texto):
    """Reemplaza números escritos en palabras por dígitos"""
    # Busca todas las palabras que puedan ser números
    palabras = texto.split()
    for i, palabra in enumerate(palabras):
        numero = palabra_a_numero(palabra)
        if numero is not None:
            palabras[i] = str(numero)
    return ' '.join(palabras)

def resolver_captcha(texto_original):
    # Paso 1: Normalizar el texto (números en palabras → dígitos)
    texto_normalizado = preprocesar_texto(texto_original)
    
    # Paso 2: Buscar números a excluir
    patron_exclusion = r'no tenga en cuenta el número (\d+)|ignore el número (\d+)'
    match_exclusion = re.search(patron_exclusion, texto_normalizado, re.IGNORECASE)
    
    numeros_a_ignorar = []
    if match_exclusion:
        num = int(match_exclusion.group(1) or match_exclusion.group(2))
        numeros_a_ignorar.append(num)
    
    # Paso 3: Buscar la operación
    patron_operacion = r'(\d+)\s*([+\-×÷*/])\s*(\d+)'
    match = re.search(patron_operacion, texto_normalizado)
    
    if not match:
        return None
    
    num1 = int(match.group(1))
    operador = match.group(2)
    num2 = int(match.group(3))
    
    # Paso 4: Aplicar exclusiones
    if num1 in numeros_a_ignorar:
        num1 = 0
    if num2 in numeros_a_ignorar:
        num2 = 0
    
    # Paso 5: Resolver
    return resolver_operacion(num1, operador, num2)

# Pruebas avanzadas
print(resolver_captcha("Calcule 10 * 3, no tenga en cuenta el número 4"))  
# Output: 30

print(resolver_captcha("Calcule cuatro * tres, no tenga en cuenta el número 4"))
# Output: 0 (porque 4 * 3 se convierte en 0 * 3)

print(resolver_captcha("Realice cinco más tres"))
# Output: 8

🎯 Recomendación Final para tu Prototipo

  1. Empieza simple: Concéntrate primero en resolver los casos más comunes (números en dígitos, una sola exclusión).

  2. Loggea todo: Guarda el texto original, el texto procesado y el resultado. Esto te ayudará a identificar patrones y mejorar el parser.

  3. Prueba con ejemplos reales: Si la web es pública, prueba tu script con varios ejemplos diferentes para ver todas las variantes que usa.

  4. Maneja errores: Si tu parser falla, que el script lo registre y puedas analizar manualmente el caso.

¿Quieres que profundice en algún aspecto específico? Por ejemplo, cómo manejar operaciones con más de 2 números, cómo interpretar "no tenga en cuenta" en diferentes contextos, o cómo integrar esto con Selenium para llenar automáticamente el campo de respuesta.

¿Hay posibilidad de que el flujo de navegación tenga partes automatizadas y otras partes manuales?

¡Absolutamente sí! De hecho, es una práctica muy común y recomendada, especialmente en proyectos unipersonales como el tuyo. La idea de tener un flujo híbrido (automatizado + manual) no solo es viable, sino que puede ser la clave para que tu proyecto sea funcional y sostenible.


🎯 ¿Por qué considerar un flujo híbrido?

VentajaExplicación
Resuelve problemas complejosLos CAPTCHA y los desafíos de humanidad son difíciles de automatizar al 100%. Un toque manual puede ser más barato y rápido que implementar soluciones complejas.
Ahorra tiempo de desarrolloNo necesitas programar una solución perfecta para cada variante del desafío. Puedes enfocarte en lo que la máquina hace bien y dejar lo difícil para el humano.
Mayor flexibilidadSi el sitio web cambia su diseño o su CAPTCHA, tu flujo híbrido se adapta más fácilmente que un script 100% automatizado.
Reduce costosEvitas tener que pagar por servicios de resolución de CAPTCHA (como 2Captcha) si el volumen de leads no es masivo.

🔄 Arquitectura de un Flujo Híbrido para tu Proyecto

Imagina este flujo de trabajo para tu controlador de leads:

Paso 1: Automatizado - Extracción y Preparación

python
# Script en Python/Selenium
1. El scraper toma el número de documento del lead desde la base de datos.
2. Abre el navegador y navega a la página de consulta.
3. Llena el campo del número de documento.
4. Detecta qué tipo de desafío aparece (CAPTCHA de texto o matemático).
5. Si es matemático, intenta resolverlo automáticamente con la lógica que ya desarrollamos.

Paso 2: Punto de Decisión - ¿Automatizar o Pedir Ayuda?

python
# Lógica de decisión en el script
if desafío_es_matemático_y_resoluble():
    # Automatiza completamente
    resolver_y_enviar()
    resultado = extraer_información()
    actualizar_base_datos(resultado)
else:
    # CAPTCHA complejo o no reconocido
    # ENVÍA ALERTA AL HUMANO
    enviar_notificación_al_operador(lead_id, captcha_screenshot)

Paso 3: Manual - Intervención Humana

El operador (tú o un asistente) recibe una notificación (email, Telegram, o panel de administración) con:

  • El número de documento del lead.

  • Una captura de pantalla del CAPTCHA.

  • Un enlace o botón para "resolver manualmente".

El operador:

  1. Abre la página (o el script ya la tiene abierta esperando).

  2. Resuelve el CAPTCHA manualmente.

  3. Confirma que el proceso continúe.

Paso 4: Automatizado - Continuación y Registro

python
# Una vez resuelto manualmente, el script continúa
1. Extrae la información de la página (si el lead está activo o no).
2. Actualiza la base de datos con el resultado.
3. Registra que este lead fue procesado (para no repetirlo en el mes).
4. Pasa al siguiente lead.

🛠️ Cómo Implementarlo Técnicamente

Opción 1: Pausa y Reanudación con Selenium

python
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import json

def proceso_con_intervencion_manual(driver, lead_id):
    # 1. Automatizado: Navegar y llenar formulario
    driver.get("https://ejemplo.com/consulta")
    campo_documento = driver.find_element(By.ID, "documento")
    campo_documento.send_keys(lead_id)
    
    # 2. Intentar resolver automáticamente
    desafio_texto = driver.find_element(By.CLASS_NAME, "captcha-text").text
    resultado = resolver_captcha(desafio_texto)
    
    if resultado is not None:
        # Automatizado: Resolver y enviar
        campo_respuesta = driver.find_element(By.ID, "captcha-response")
        campo_respuesta.send_keys(str(resultado))
        driver.find_element(By.ID, "submit").click()
    else:
        # MANUAL: Guardar estado y esperar intervención
        print(f"⚠️ Lead {lead_id} necesita intervención manual")
        
        # Guardar captura de pantalla
        driver.save_screenshot(f"captcha_lead_{lead_id}.png")
        
        # Guardar estado en archivo o BD para retomar después
        with open("pendientes_manual.json", "a") as f:
            json.dump({"lead_id": lead_id, "timestamp": time.time()}, f)
        
        # Esperar a que el operador resuelva (podría ser con un loop o señal)
        # ... lógica de espera ...
        
        # Reanudar después de la intervención manual
        # El operador dejó el CAPTCHA resuelto y el formulario listo para enviar
        driver.find_element(By.ID, "submit").click()
    
    # 4. Automatizado: Extraer resultado
    if "activo" in driver.page_source:
        actualizar_base_datos(lead_id, "activo")
    else:
        actualizar_base_datos(lead_id, "inactivo")

Opción 2: Cola de Trabajo con Interfaz Web (Más Profesional)

  1. Jobs en Laravel: Cada lead se encola como un Job.

  2. Worker en Python: Un worker independiente (usando Celery o similar) procesa los jobs.

  3. Panel de Administración: Una interfaz web donde ves los leads que necesitan intervención manual.

  4. Mecanismo de Reintento: Cuando resuelves manualmente, marcas el job como "listo para continuar".

php
// En Laravel - Job para procesar lead
class ProcesarLead implements ShouldQueue
{
    public function handle()
    {
        // Llamar al scraper en Python
        $resultado = shell_exec("python3 scraper.py " . $this->lead->documento);
        
        if (strpos($resultado, 'NEEDS_MANUAL') !== false) {
            // Marcar el lead como "pendiente de revisión manual"
            $this->lead->estado = 'pendiente_manual';
            $this->lead->save();
            
            // Notificar al operador (email, Telegram, etc.)
            Notification::send($operador, new LeadPendiente($this->lead));
        } else {
            // Actualizar el lead con el resultado
            $this->lead->estado = $resultado;
            $this->lead->save();
        }
    }
}

📊 Cuándo Usar cada Enfoque

SituaciónRecomendación
Pocos leads (< 50 por día)Flujo híbrido con intervención manual en todos los casos difíciles. El costo de tiempo humano es bajo.
Muchos leads (> 500 por día)Invierte en mejorar el parser matemático y considera usar una API de resolución de CAPTCHA (2Captcha) para los casos difíciles.
CAPTCHA cambia frecuentementeEl flujo híbrido es ideal. Automatizas lo que puedes y dejas lo cambiante para el humano.
Proyecto en fase de prototipoUsa el flujo híbrido desde el principio. Te permite probar y validar el negocio sin tener que resolver el 100% de la automatización.
El sitio tiene muchos tipos de CAPTCHAAutomatiza solo los más comunes y deja el resto para intervención manual.

💡 Recomendación Final para tu Proyecto

Para tu controlador de leads, te sugiero esta estrategia:

  1. Implementa un parser matemático robusto para los desafíos más comunes (como el que ya empezamos a desarrollar).

  2. Agrega un "modo de rescate" en tu script: si el parser falla o no reconoce el desafío, que el script:

    • Tome una captura de pantalla.

    • Guarde el estado (lead_id, URL, momento).

    • Marque el lead como "pendiente de revisión manual".

  3. Crea un panel simple en Laravel donde puedas ver estos leads pendientes y, con un clic, abrir la página para resolver el CAPTCHA manualmente.

  4. Una vez resuelto manualmente, un botón en el panel reanuda el procesamiento automático (extracción de resultados y actualización de BD).

Este enfoque te da lo mejor de ambos mundos: eficiencia automatizada para el 80-90% de los casos y flexibilidad manual para los casos difíciles. Y lo mejor: puedes empezar a usar tu aplicación desde el día 1, incluso antes de tener la automatización al 100%.

¿Te gustaría que profundice en cómo implementar el panel de administración en Laravel para gestionar estos casos manuales?

Comentarios

Entradas populares de este blog

Crear proyecto de frontend con Vite, React, Tailwind, Typescript y JSX

 ¿Cómo se crea un proyecto exclusivo de frontend con Vite, React, Tailwind, Typescript y JSX? ¡Absolutamente! Entiendo que quieres la guía completa para pasar de cero a tener un proyecto de frontend moderno, vacío y listo para ser llenado con tu código. A continuación, te proporciono un archivo de guía detallada que incluye todos los comandos necesarios para inicializar el proyecto, configurar Tailwind CSS, y los pasos clave para empezar a "poblarlo". Voy a generar un documento Markdown con la guía paso a paso, incluyendo los comandos de terminal y las modificaciones esenciales a los archivos de configuración. Guía: Creación de un Proyecto Frontend Puro (Vite, React, TypeScript, Tailwind) Este documento detalla el proceso para inicializar un proyecto de frontend vacío y optimizado, utilizando Vite como empaquetador, React como librería, TypeScript para tipado y Tailwind CSS para estilizado. 1. Inicialización del Proyecto con Vite Vite es la herramienta más rápida para emp...

Tokens V2

Tokens: Programme to discover tokens, where there are not. Now available at  https://puszcza.gnu.org.ua/projects/tokens/ This is Version 2, for  version 1, go here . Synopsis: use TokensV2; sub printFile; my @FORMAT = ( ['<Message Date=".*?" Time=".*?" DateTime=".*?" SessionID=".*?"><From>(?:<User FriendlyName=".*?"/>)+</From><To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style=".*?")?>.*?</Text></Message>',   sub {     my $fh = $_[1];     my ($d, $t, $f, $s, $T) = $_[0] =~ m|<Message Date="(.*?)" Time="(.*?)" DateTime=".*?" SessionID=".*?">(<From>(?:<User FriendlyName=".*?"/>)+</From>)<To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style="(.*?)")?>(.*?)</Text></Message>|;     my $F = join '<br />', ...

Perl Net::LDAP::SimpleServer

Adaptaciones sobre el módulo LDAP Server para Windows (Strawberry Perl) Lista de adaptaciones (continúa más abajo): - Relajación de condiciones de bind:     - Cuenta principal (principal account)     - Validación de contraseñas Ubicación del archivo: %Strawberry_Perl%\site\lib\net\ldap\SimpleServer\ProtocolHandler.pm CPAN: http://search.cpan.org/~russoz/Net-LDAP-SimpleServer-0.0.17/lib/Net/LDAP/SimpleServer.pm Código: package Net::LDAP::SimpleServer::ProtocolHandler; use strict; use warnings; # ABSTRACT: LDAP protocol handler used with Net::LDAP::SimpleServer our $VERSION = '0.0.17';    # VERSION use Net::LDAP::Server; use base 'Net::LDAP::Server'; use fields qw(store root_dn root_pw allow_anon); use Carp; use Net::LDAP::LDIF; use Net::LDAP::Util qw{canonical_dn}; use Net::LDAP::FilterMatch; use Net::LDAP::Constant (     qw/LDAP_SUCCESS LDAP_AUTH_UNKNOWN LDAP_INVALID_CREDENTIALS/,   ...