Scraping de datos web con BeautifulSoup y Selenium

Última actualización: 28/01/2026
Autor: Isaac
  • Combinar BeautifulSoup y Selenium permite extraer datos tanto de páginas estáticas como dinámicas.
  • Requests y BeautifulSoup son ideales para HTML directo, mientras Selenium automatiza navegadores y JavaScript.
  • Es clave respetar robots.txt, la legalidad y aplicar buenas prácticas para escalar y mantener scrapers.
  • APIs y herramientas no-code como Octoparse son alternativas útiles según el perfil y las necesidades del proyecto.

Guía de scraping de datos web con BeautifulSoup y Selenium

Si hoy tuvieras que recopilar precios, opiniones o listados completos de productos de la web a mano, probablemente acabarías desesperado. Copiar y pegar fila a fila no solo es aburridísimo, sino que además es una fuente perfecta de errores humanos. Por suerte, tenemos herramientas como Python, BeautifulSoup y Selenium que permiten automatizar todo este proceso de forma controlada y reproducible.

En este artículo vamos a hacer un repaso a fondo, pero con un tono cercano y práctico, de cómo combinar scraping estático con BeautifulSoup y scraping dinámico con Selenium. Verás en qué casos usar cada enfoque, cómo se complementan, qué problemas típicos te vas a encontrar (iframes, JavaScript, CAPTCHAs, cambios de estructura…) y también tocaremos temas clave como la legalidad, la ética, los robots.txt y alternativas como las APIs o herramientas no-code.

Qué es exactamente el web scraping y cuándo tiene sentido usarlo

El web scraping es el proceso de extraer automáticamente información de páginas web diseñadas para humanos, transformando ese contenido HTML (y a veces también el generado con JavaScript) en datos estructurados que puedas usar: tablas, JSON, CSV, cargas a una base de datos, etc.

La idea es que un programa haga lo que haría un usuario delante del navegador: visitar URLs, seguir enlaces, localizar partes concretas de la página (títulos, precios, comentarios, imágenes, botones), extraer el contenido y guardarlo para analizarlo posteriormente.

Los casos de uso más habituales del scraping de datos web son muy variados: desde comparar precios de productos en distintos e-commerce, hasta monitorizar a la competencia, recoger reseñas o comentarios, seguir menciones de marca, generar leads a partir de listados públicos o crear datasets para proyectos de machine learning.

Sin embargo, el scraping debería ser siempre tu “última opción” cuando no tengas una API oficial u otra vía estructurada de acceso a los datos. Es frágil (las páginas cambian), puede chocar con políticas de uso del sitio y, si necesitas recorrer mucha “basura” para llegar a lo que te interesa, puede ser lento o costoso en recursos.

Antes de escribir una sola línea de código de scraping conviene hacerse varias preguntas clave: ¿hay API oficial?, ¿estoy violando los términos y condiciones del sitio?, ¿respeto la legislación local sobre protección de datos y uso de la información?, ¿el uso que voy a darle a esos datos es legal y ético?

Conceptos y usos del web scraping

Cómo funciona la web “de verdad”: HTML, CSS, JavaScript, iframes y DOM

Sobre el papel, una página web es algo bastante razonable: HTML para la estructura, CSS para el aspecto y JavaScript para darle vida. Pero cuando te pones a rascar páginas reales, descubres que el HTML puede ser un infierno, el CSS irrelevante para tus datos y el JavaScript una caja negra que manipula el contenido a su antojo.

Cuando pulsas Enter en el navegador, este envía una petición HTTP al servidor, recibe una respuesta y la muestra formateada. Si haces “Ver código fuente de la página” ves el HTML tal cual ha venido del servidor, antes de que JavaScript meta mano al DOM.

El DOM (Document Object Model) es la representación viva de la página dentro del navegador. JavaScript puede añadir, quitar o modificar nodos del DOM después de que se haya descargado el HTML inicial. Por eso, a veces en el código fuente no aparece el contenido que ves realmente en pantalla.

Un ejemplo típico son los sistemas de comentarios como Disqus, o embeds de terceros, que se insertan a través de iframes. Puede ocurrir que, al inspeccionar el HTML original, no encuentres ni rastro del iframe, porque se inyecta dinámicamente con JavaScript una vez cargada la página.

Esta diferencia entre “ver código fuente” y el DOM final es lo que marca la frontera entre scraping estático y scraping dinámico: en el primero solo ves el HTML que viene del servidor; en el segundo necesitas un navegador (real o headless) que ejecute JavaScript y te deje acceder al DOM resultante.

Scraping estático con Python, Requests y BeautifulSoup

Scraping estático con BeautifulSoup

Siempre que el contenido que necesitas esté en el HTML “tal cual” viene del servidor, lo más sencillo, rápido y robusto es hacer scraping estático. Para eso, en Python se suele combinar la librería requests (para hacer peticiones HTTP) con BeautifulSoup (para parsear y navegar el HTML).

Requests te permite hacer una llamada tan simple como r = requests.get(url) y, a partir del objeto de respuesta, comprobar si la petición ha ido bien con r.ok o revisar el código de estado HTTP y el contenido recibido. Para trabajar con texto suele ser buena idea decodificar en UTF-8.

BeautifulSoup toma el HTML que has descargado y lo convierte en un árbol de objetos Python sobre los que puedes buscar etiquetas, atributos, texto, elementos anidados, etc. Basta con crear algo del estilo sopa = BeautifulSoup(respuesta.text, ‘html.parser’) para empezar a jugar.

A partir de ahí, puedes localizar prácticamente cualquier elemento con métodos como find, find_all o select. Por ejemplo, sacar todos los enlaces de una página sería tan simple como obtener todas las etiquetas <a> y leer su atributo href.

  Cómo encender la linterna del móvil sin tocarlo: todos los métodos

Un patrón muy típico es recorrer listados repetitivos, como artículos, productos o entradas de blog. Imagina una página donde cada tutorial está dentro de una etiqueta <article>: podrías buscar todas esas etiquetas, meterte en cada una, localizar el enlace, el título, la fecha, etc., y generar una lista de diccionarios o un DataFrame de Pandas.

BeautifulSoup también es muy útil para extraer datos de tablas HTML, como las de Wikipedia. Una técnica frecuente es localizar la etiqueta <table> que te interesa y usar pandas.read_html para convertirla directamente en un DataFrame, que luego puedes exportar a CSV o procesar para análisis estadístico o modelos de machine learning.

En proyectos algo más serios, lo habitual es envolver la lógica de scraping en funciones: una que descarga y parsea la página, otra que extrae los enlaces relevantes, otra que a partir de una URL de detalle devuelve un diccionario con todos los campos de interés listo para guardar en una base de datos.

No hay que olvidar gestionar errores con try-except. Si una petición falla o una estructura HTML cambia, lanzar una excepción sin controlar puede tirar abajo todo el proceso. Manejar las excepciones permite saltar páginas problemáticas, registrar los fallos y seguir adelante.

Scraping dinámico: cuándo BeautifulSoup ya no basta

El scraping estático se queda corto cuando el contenido que quieres se genera con JavaScript: menús que cargan datos al hacer clic, comentarios embebidos, listados paginados que se actualizan sin recargar la página, campos que aparecen solo tras un login, etc.

En estos casos, aunque hagas requests.get(url), el HTML que recibes no contiene la información final. Solo ves plantillas, scripts minificados, trozos de marcados incompletos y poco más. Lo que falta lo inserta JavaScript una vez que la página se ejecuta en el navegador.

El scraping dinámico introduce un navegador real o “sin cabeza” (headless) que sí ejecuta JavaScript y construye el DOM definitivo. Tu script no solo descarga la página, sino que la “navega”: hace clic en botones, rellena formularios, cambia pestañas, espera a que se carguen elementos y, entonces, extrae los datos.

La herramienta reina en este terreno es Selenium WebDriver. Nació para pruebas automatizadas de aplicaciones web, pero su capacidad para controlar el navegador lo convierte en un aliado buenísimo para scraping de sitios complejos y dinámicos.

Con Selenium controlas el navegador como si fueras un usuario real: puedes abrir una URL, localizar elementos por id, clase, CSS selector o XPath, hacer clic, enviar texto (para logins, formularios, buscadores), cambiar de iframe, gestionar ventanas o pestañas y, finalmente, leer el DOM que devuelve driver.page_source o extraer texto directamente de los elementos.

Instalar y configurar Selenium, drivers y navegadores

Para trabajar con Selenium necesitas dos piezas: la librería de Python y el driver del navegador que vayas a automatizar. Puedes usar Chrome, Firefox u otros navegadores, pero Chrome y Firefox suelen ser la apuesta segura.

La instalación básica en Python es tan simple como lanzar un pip install selenium. A partir de ahí, tienes que descargar el driver correspondiente (por ejemplo, geckodriver para Firefox o chromedriver para Chrome), colocarlo en una ruta accesible y añadir esa ruta al PATH del sistema si quieres evitar dar la ruta absoluta en tu script.

En Windows, por ejemplo, pondrías el .exe del driver en una carpeta a tu gusto y añadirías esa carpeta a la variable de entorno PATH. En Linux o macOS el proceso es similar, cambiando la forma de configurar las variables de entorno.

Hoy en día, en muchos casos basta con indicar la ruta del driver al crear el objeto WebDriver, por ejemplo con Chrome: configurando un ChromeService con la ruta a chromedriver y pasando ese servicio a webdriver.Chrome junto con las opciones del navegador.

Puedes usar navegadores con interfaz visible o en modo headless. El modo headless ahorra recursos y es ideal para automatizaciones en servidores, pero conviene probar primero en modo visible para depurar problemas de interacción con la página.

Scraping dinámico real: de logins, iframes y elementos generados con JS

Una vez tienes tu WebDriver inicializado, puedes empezar a automatizar escenarios que con BeautifulSoup serían un dolor. Por ejemplo, iniciar sesión en un sitio que requiere usuario y contraseña antes de mostrar la información que necesitas.

El flujo típico con Selenium para una página protegida por login es: abrir la URL, localizar los inputs de usuario y contraseña, enviar las credenciales, hacer clic en el botón de acceso y esperar a que cargue el contenido privado. A partir de ahí puedes extraer datos como en cualquier página.

Otro ejemplo potente es contar los comentarios de una plataforma como Disqus integrados en una página de tutoriales. Muchas veces esos comentarios están dentro de un iframe que ni siquiera aparece en el HTML inicial: se genera con JavaScript y se inserta con un id como disqus_thread.

Con Selenium puedes localizar ese contenedor, cambiar el contexto al iframe correspondiente, esperar a que se carguen elementos como el contador de comentarios y leer el valor. Sin Selenium, con solo requests y BeautifulSoup, en este caso tienes poco que rascar.

Los iframes y el contenido tardío implican que no basta con pedir page_source inmediatamente después de cargar la página. A menudo es necesario usar esperas explícitas (esperar a que exista un elemento o a que sea visible) antes de extraer datos, para no quedarse a medias.

  La forma sencilla de voltear, girar o voltear una imagen en Photoshop

En cuanto a herramientas de apoyo, además del navegador que controla Selenium, puedes utilizar DevTools para inspeccionar el DOM y localizar las clases, ids o selectores CSS que necesitas. Esto es crucial para encontrar patrones repetitivos (filas de una tabla, tarjetas de producto, bloques de comentarios) que después recorrerás en bucle.

Combinando Selenium y BeautifulSoup: lo mejor de ambos mundos

Una estrategia muy potente es usar Selenium solo para lo que realmente requiere un navegador y delegar el parsing pesado en BeautifulSoup. De esta manera, Selenium se encarga de “preparar” la página (clicks, logins, scroll, filtros) y luego pasas el HTML resultante a BeautifulSoup para una extracción más cómoda.

Por ejemplo, imagina que quieres raspar una página que genera una tabla de 100 nombres de Star Wars al pulsar un botón. Con Selenium puedes localizar el radio button con valor 100, hacer clic, luego localizar el botón “Generate!” y volver a hacer clic para que se rellene la tabla.

Una vez la tabla esté en el DOM, puedes recuperar driver.page_source y alimentar a BeautifulSoup. A partir de ahí, buscas la tabla concreta (por índice, id o clase), recorres las celdas <td>, limpias el texto (quitando espacios, saltos de línea, caracteres raros como u’\xa0′) y vas añadiendo cada nombre a una lista, comprobando que no haya duplicados.

Si repites ese ciclo en un bucle hasta llegar, por ejemplo, a 100.000 nombres, Selenium se encarga de la parte interactiva y BeautifulSoup de la extracción. El resultado puedes volcarlo en un DataFrame de Pandas y exportarlo a CSV, perfectos para alimentar un modelo de machine learning o cualquier análisis posterior.

Este mismo patrón de “Selenium para interactuar, BeautifulSoup para parsear” se puede aplicar a multitud de sitios dinámicos: seleccionas filtros, cambias de página, haces scroll para cargar más resultados y, cuando el DOM ya contiene lo que te interesa, pasas el HTML a BeautifulSoup para extraerlo con precisión.

Scraping a gran escala, proyectos reales y herramientas complementarias

En un contexto profesional, rara vez te quedas en un script pequeñito: acabas montando scrapers más complejos que recorren muchas páginas y generan grandes volúmenes de datos. Aquí entran en juego también herramientas como Scrapy para escalado y organización del proyecto.

Un ejemplo clásico de proyecto didáctico es construir un scraper de noticias de un diario online como Página 12. Para ello puedes usar requests y BeautifulSoup para descargar la página de portada, localizar las secciones, extraer los enlaces de cada una y, después, visitar cada noticia por separado.

La lógica suele dividirse en varias funciones: una para obtener las secciones, otra para listar las URLs de las noticias de una sección y otra para extraer el contenido detallado de cada nota. Esta última puede devolver un diccionario con título, fecha, cuerpo de la noticia, autor, categoría, imagen principal, etc.

Además del texto, es habitual descargar el contenido multimedia asociado, como la imagen principal. Para ello solo tienes que localizar el atributo src de la etiqueta <img> que te interesa y lanzar otra petición con requests.get para guardar el archivo en disco.

En la práctica, cuando realizas muchos requests contra un mismo sitio es fundamental ser educado con el servidor: espaciar las peticiones, respetar posibles indicaciones de crawl-delay en robots.txt y no lanzar cientos de hilos que puedan tumbar la web objetivo.

Scrapy entra en juego cuando necesitas scraping a gran escala: proporciona un framework completo con spiders, colas de peticiones, manejo de errores, pipelines para procesar y almacenar datos y facilidades para respetar robots.txt y reglas de acceso.

Legalidad, ética y robots.txt en el scraping de datos web

El tema legal del web scraping no es blanco o negro, sino una zona gris que hay que tratar con cuidado. Que algo esté técnicamente accesible no implica que puedas hacer lo que quieras con ello.

Hay cuatro preguntas básicas que deberías hacerte siempre antes de scrapear un sitio: ¿estoy incumpliendo alguna ley local o regional?, ¿estoy violando los términos y condiciones del servicio?, ¿estoy accediendo a secciones que el propietario no considera públicas?, ¿el uso final que voy a dar a los datos es legítimo?

Un archivo clave que conviene revisar es robots.txt. Lo encontrarás añadiendo /robots.txt a la raíz del dominio, por ejemplo: https://www.ejemplo.com/robots.txt. Allí el propietario indica qué rutas pueden visitar los crawlers y cuáles quiere mantener fuera.

Las directivas más habituales son Disallow, que marca rutas no deseadas, y Crawl-delay, que especifica el número de segundos de espera entre peticiones. Aunque robots.txt no es una ley en sí misma, respetarlo es una buena práctica y suele ser un indicador de la voluntad del propietario del sitio.

Desde el punto de vista de la ética profesional, es importante no saturar servidores ni extraer información sensible o privada. Si tienes dudas, lo mejor es contactar con los responsables del sitio o buscar si ofrecen una API oficial o datasets preparados para su consumo.

Tampoco hay que olvidar regulaciones sobre protección de datos personales. Si vas a tratar datos de usuarios, opiniones, perfiles, etc., deberás tener clara la base legal y las implicaciones de privacidad.

Retos técnicos habituales: cambios de estructura, anti-bot y escalabilidad

Uno de los mayores quebraderos de cabeza del scraping es que las webs cambian su estructura sin previo aviso. Un cambio de clase CSS, un rediseño de la plantilla o una nueva forma de cargar los contenidos puede romper tu scraper de la noche a la mañana.

  Formas de utilizar WhatsApp en una tableta Android

Por eso es importante diseñar el código con cierta tolerancia a cambios menores: no depender en exceso de selectores frágiles, validar que los elementos existen antes de usarlos y escribir funciones fáciles de actualizar cuando algo se rompa.

Otro frente son las medidas anti-bot que implementan muchos sitios: bloqueo por IP, detección de patrones de tráfico, desafíos JavaScript avanzados, CAPTCHAs, detección de navegadores automatizados, etc.

Para lidiar con estas barreras se utilizan técnicas como el uso de proxies (a veces rotativos), cabeceras que simulan navegadores reales, periodos de espera aleatorios entre peticiones y navegadores headless que se comportan de forma lo más humana posible. Incluso existen navegadores “anti-detección” y servicios especializados que intentan camuflar la automatización.

Con Selenium, por ejemplo, puedes conectarte a navegadores personalizados o antifraude mediante direcciones de depuración remota. Algunos servicios permiten lanzar un navegador con una huella específica (user-agent, hardware, sistema operativo) y conectarte con WebDriver a través de un puerto de debug.

La escalabilidad es otro reto: a medida que crece el volumen de datos y de páginas a visitar, necesitas paralelizar o distribuir el scraping. Esto puede implicar lanzar varios procesos o incluso desplegar spiders en distintos servidores, controlando siempre la carga que impones al sitio objetivo.

Alternativas al web scraping clásico: APIs y herramientas sin código

Aunque el scraping directo del HTML es tremendamente flexible, no siempre es la mejor ni la única opción. En muchos casos merece la pena explorar alternativas.

La primera alternativa son las APIs oficiales. Algunos sitios exponen endpoints bien documentados que te devuelven datos en JSON o XML de forma estructurada y estable. Suelen tener límites de uso, pero a cambio son mucho más robustas y claras legalmente que scrapear directamente el HTML.

Otra opción es adquirir o reutilizar conjuntos de datos ya preparados, gratuitos o de pago. Si lo que necesitas son datos históricos, y alguien ya los ha recopilado con calidad razonable, quizá no tenga sentido reinventar la rueda montando tu propio scraper.

Para quienes no quieren o no pueden programar, existen herramientas no-code de scraping como Octoparse. Ofrecen una interfaz visual para señalar los elementos que quieres extraer, programar ejecuciones periódicas en la nube y exportar resultados a CSV, Excel o JSON sin escribir una línea de código.

Octoparse suele ser una buena elección cuando necesitas rapidez y no tienes experiencia técnica: permite scrapear sitios estáticos y dinámicos apoyándose en navegadores integrados, y facilita la automatización y planificación de tareas sin tener que pelearte con Selenium ni con BeautifulSoup.

La elección entre BeautifulSoup y una herramienta como Octoparse depende mucho de tu perfil y necesidades: si buscas control fino, libertad total y soluciones gratuitas, programar con Python es la vía lógica; si priorizas la simplicidad y una curva de aprendizaje baja, un entorno no-code puede ser más cómodo.

Buenas prácticas de desarrollo: entornos, errores y organización del código

Cuando empiezas a tomarle el gusto al scraping, es fácil caer en scripts caóticos; por eso conviene aplicar un mínimo de disciplina de desarrollo. Crear entornos virtuales, separar el código en módulos y documentar lo que hace cada parte te ahorrará dolores de cabeza.

En proyectos profesionales lo habitual es crear una carpeta para el proyecto, montar un entorno virtual con venv o pipenv e instalar solo las dependencias necesarias: requests, beautifulsoup4, selenium, pandas, jupyter si vas a experimentar en notebooks, etc.

Trabajar primero en Jupyter o similar puede ayudarte a prototipar y depurar, pero una vez el scraper está estable tiene sentido empaquetar la lógica en scripts o módulos reutilizables, con funciones claras para cada tarea: descargar, parsear, procesar, guardar.

El manejo de errores con try-except es básico en scraping. No todas las páginas responden bien, a veces hay timeouts, a veces cambian las clases HTML, otras veces algún campo viene vacío. En lugar de dejar que el programa se estrelle, captura las excepciones, registra qué URL ha fallado y continúa con el resto.

Por último, es buena idea encapsular la lógica de extracción en funciones que devuelvan estructuras homogéneas como diccionarios o dataframes. Esto facilita guardar los resultados en bases de datos, archivos CSV o JSON, o incluso integrarlos en pipelines más complejos de análisis de datos e inteligencia artificial.

En definitiva, combinar scraping estático con BeautifulSoup y scraping dinámico con Selenium te permite abordar prácticamente cualquier escenario de extracción de datos web, desde una simple tabla de Wikipedia hasta un portal con login, JavaScript pesado e iframes embebidos. Con un poco de cuidado en la parte legal y ética, una buena arquitectura de código y herramientas auxiliares como requests, pandas o incluso plataformas no-code, puedes transformar montañas de HTML caótico en información estructurada lista para tomar decisiones, entrenar modelos o alimentar tus próximos proyectos de datos.