← Todos los artículos

Tutorial de web scraper en Python: domina la extracción de datos con herramientas modernas

En esencia, el web scraping en Python es un sencillo baile de dos pasos: primero obtienes una página web y luego extraes la información específica que necesitas. La magia reside en las bibliotecas que hacen que este proceso sea sorprendentemente directo, incluso para sitios complejos.

Esta guía te llevará paso a paso por la construcción de tus propios scrapers, empezando por los fundamentos y avanzando hacia las técnicas avanzadas que necesitarás para proyectos del mundo real.

La demanda de datos web está disparándose. El mercado de software de web scraper se valoró en USD 718,86 millones en 2024 y va camino de superar los USD 2.200 millones para 2033. Hay una razón por la que Python es el lenguaje preferido aquí: se espera que impulse casi el 70% del stack de los desarrolladores para scraping en 2026. Su sintaxis limpia y sus potentes herramientas encajan a la perfección con esta tarea.

Tu kit de herramientas de web scraping en Python

Antes de escribir una sola línea de código, necesitas conocer tus herramientas. Diferentes trabajos requieren diferentes bibliotecas, pero para la mayoría de los sitios web estáticos, tu paquete inicial es sencillo. Aquí tienes un vistazo rápido a las bibliotecas principales con las que te encontrarás y cuándo recurrir a ellas.

Biblioteca

Caso de uso principal

Ideal para

Requests

Enviar solicitudes HTTP

Obtener el HTML en bruto de páginas web estáticas.

BeautifulSoup

Parsear HTML/XML

Navegar y extraer datos del HTML que has obtenido.

Playwright/Selenium

Automatización de navegador

Hacer scraping de sitios dinámicos con mucho JavaScript que cargan contenido después de la carga inicial de la página.

Esta tabla te da un punto de partida. Como veremos, a menudo combinarás estas herramientas para afrontar los distintos desafíos que un sitio web puede plantearte.

El stack clásico: Requests y BeautifulSoup

Para incontables sitios web, todo el contenido que necesitas está ahí mismo, en el código fuente HTML inicial. Aquí es donde brilla el dúo clásico de y .

Piensa en la biblioteca Requests como tu mensajero digital. Va hasta un servidor, “llama a la puerta” enviando una solicitud HTTP y trae de vuelta lo que el servidor devuelva, normalmente el HTML en bruto de la página. Es sencilla, fiable y el primer paso de casi cualquier script de scraping.

Una vez que ha entregado el HTML, te queda un bloque de texto grande y desordenado. Ahí es donde entra BeautifulSoup. Toma ese revoltijo de HTML y lo convierte en un objeto estructurado por el que puedes navegar fácilmente. Luego puedes indicarle que encuentre elementos específicos, como todos los precios de productos, títulos de artículos o enlaces de una página, usando sus etiquetas HTML y clases CSS.

Para un enfoque ligeramente distinto de estos fundamentos, este detallado Python Web Scraping Tutorial es un gran recurso para reforzar los conceptos.

Pero ¿qué pasa cuando los datos no están en el HTML inicial? Ahí es cuando necesitamos sacar la maquinaria pesada para manejar contenido dinámico, que cubriremos a continuación.

Hacer scraping de sitios estáticos con Requests y BeautifulSoup

Muy bien, manos a la obra: vamos a construir nuestro primer web scraper. Empezaremos con la fruta más fácil de la web: los sitios estáticos. Son páginas donde el contenido que ves se entrega en el documento HTML inicial desde el servidor. No hay JavaScript complejo cargando datos en segundo plano, lo que las convierte en el campo de entrenamiento perfecto.

Para este trabajo, nuestro kit de referencia es un dúo clásico de Python: Requests y BeautifulSoup. Piénsalo así: es la herramienta que sale a buscar el HTML en bruto de una URL. Una vez que tienes ese revoltijo de código, entra para darle sentido, convirtiendo el HTML en un objeto estructurado que podemos desmenuzar fácilmente.

Configurar tu primer scraper

Lo primero de todo: necesitamos obtener el contenido de la página. Antes de escribir cualquier lógica de parseo, siempre conviene asegurarse de que puedes conectarte con éxito a tu objetivo.

Para empezar, tendrás que instalar las bibliotecas. Simplemente abre tu terminal y ejecuta este comando:

Con nuestras herramientas listas, bastan unas pocas líneas de Python para hacer una solicitud. Nuestro objetivo inicial es sencillo: obtener de vuelta un código de estado 200 OK. Es la señal universal de “éxito”.

import requests

url = “https://sandbox.oxylabs.io/products

response = requests.get(url)

if response.status_code == 200: print(“Successfully fetched the page!”) # We will add our parsing logic here later else: print(f”Failed to fetch page. Status code: {response.status_code}”)

Si ejecutas eso y ves “Successfully fetched”, todo va bien. Si obtienes un 403 Forbidden u otro código de error, no entres en pánico. Probablemente significa que el sitio web tiene algún tipo de detección básica de bots. Más adelante abordaremos cómo sortearla.

Inspeccionar el HTML para encontrar tus objetivos

Esta siguiente parte es posiblemente la habilidad más importante que desarrollarás como scraper: usar las herramientas de desarrollador (Developer Tools) de tu navegador. Aquí empieza el verdadero trabajo de detective, ya que localizarás la estructura HTML exacta que contiene los datos que buscas.

Solo tienes que ir a la página que quieres scrapear, hacer clic derecho sobre un dato (como el nombre de un producto) y pulsar “Inspeccionar”. Aparecerá un panel mostrando el HTML del sitio, con el elemento sobre el que hiciste clic resaltado. Presta mucha atención a la etiqueta (como o ) y a sus atributos o .

Parsear y extraer datos con BeautifulSoup

Ahora que hemos identificado nuestros objetivos en el HTML, por fin podemos indicarle a BeautifulSoup qué hacer. Le daremos el HTML en bruto que obtuvimos de y usaremos selectores CSS para extraer los nombres y precios de los productos.

Construyamos sobre nuestro script anterior. Sabemos, por haber inspeccionado la página, que cada producto está en un con la clase . Dentro de ese contenedor, el nombre está en un y el precio en un con la clase .

import requests from bs4 import BeautifulSoup

url = “https://sandbox.oxylabs.io/products” response = requests.get(url)

if response.status_code == 200: # Pass the HTML content to BeautifulSoup soup = BeautifulSoup(response.text, html.parser )

else: print(f”Failed to fetch page. Status code: {response.status_code}”)

Cuando ejecutes esto, el script obtendrá la página, parseará el HTML, recorrerá cada producto que encuentre e imprimirá el nombre y el precio de cada uno. ¡Enhorabuena, oficialmente has construido un web scraper funcional!

Si quieres familiarizarte más con esta potente biblioteca, nuestra guía práctica de web scraping con BeautifulSoup cubre técnicas más avanzadas. Dominar estos fundamentos es crucial antes de pasar al mundo más complicado de los sitios web con mucho JavaScript.

Manejar contenido generado por JavaScript con Playwright

Tarde o temprano, tu fiel combo de y te fallará. Llegarás a un sitio, obtendrás el HTML y encontrarás… nada. Los precios de los productos, las reseñas de usuarios o los detalles de vuelos que buscas estarán completamente ausentes.

¿Qué está pasando? La mayoría de los sitios web modernos (piensa en tiendas de comercio electrónico, feeds de redes sociales o paneles complejos) no envían todo su contenido en el HTML inicial. En su lugar, envían un esqueleto básico y usan JavaScript para obtener y mostrar los datos después de que se carga la página. Dado que no ejecuta JavaScript, solo ve el cascarón vacío, nunca el producto terminado.

Para conseguir esos datos, tienes que dejar de simplemente solicitar una página y empezar a interactuar con ella, igual que lo haría un usuario real. Eso significa automatizar un navegador, y para ello recurrimos a herramientas como Playwright.

Por qué necesitas una herramienta de automatización de navegador

Playwright cambia las reglas del juego. Es una potente biblioteca de Python que te permite lanzar y controlar un navegador real (como Chromium, Firefox o WebKit) directamente desde tu script.

Con Playwright, tu scraper puede hacer cualquier cosa que haría una persona:

  • Hacer clic en botones y navegar por menús
  • Rellenar formularios de inicio de sesión
  • Desplazarse hacia abajo para activar contenido de carga infinita
  • Y lo más importante, esperar a que JavaScript termine de renderizar la página antes de capturar el HTML.

Esta es la clave para hacer scraping de sitios construidos con frameworks modernos como React, Vue o Angular. Si los datos que necesitas aparecen en tu pantalla un instante después de que la página se carga por primera vez, necesitas una herramienta que pueda ver lo que tú ves.

Empezar con Playwright es sencillo. Solo tienes que abrir tu terminal y ejecutar dos comandos:

El segundo comando es crucial: descarga los motores de navegador reales que Playwright controlará. Una vez hecho esto, estás listo para reescribir tu scraper y manejar contenido dinámico.

Refactorizar tu scraper para contenido dinámico

Cambiemos de estrategia. En lugar de simplemente obtener HTML, vamos a indicarle a un navegador qué hacer: ir a una URL, esperar a que aparezca un fragmento de contenido específico y luego darnos el HTML final, totalmente renderizado, para parsearlo con BeautifulSoup.

Así es como se ve en la práctica:

from playwright.sync_api import sync_playwright from bs4 import BeautifulSoup

def get_dynamic_content(url): with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(url)

url = “https://your-dynamic-site.com/products” html = get_dynamic_content(url) soup = BeautifulSoup(html, html.parser )

La magia ocurre en esta línea: . Este sencillo comando le dice a Playwright que se detenga y espere hasta que un elemento con la clase aparezca realmente en la página. Esto evita el clásico error de scrapear una página vacía antes de que JavaScript haya tenido la oportunidad de rellenarla.

Hacer este cambio tiene un impacto real. En un proyecto europeo de inteligencia de precios que vi, un equipo migró de un viejo scraper en PHP a un stack de Python y Playwright. Los resultados fueron inmediatos: las tasas de bloqueo se desplomaron de más del 40% a menos del 5%. No se trata solo de conseguir los datos; se trata de conseguirlos de forma fiable. Como muchos han comprobado, los stacks de Python superan a los métodos más antiguos cuando necesitas resultados consistentes y escalables.

Escalar tu scraper para la extracción multipágina

Extraer datos de una sola página es un gran punto de partida, pero el verdadero oro suele estar repartido por muchas páginas. Un sitio de comercio electrónico no lista todos sus productos en una sola página, y un sitio de noticias no muestra todos los artículos a la vez. Para construir un conjunto de datos con verdadera sustancia, tu scraper tiene que aprender a navegar de una página a la siguiente. Este proceso se llama manejo de la paginación.

Este es el punto en el que un simple script se convierte en un motor potente y automatizado. Tu objetivo es averiguar el sistema que usa el sitio web para organizar el contenido a lo largo de las páginas y luego construir un bucle que recorra cada una, recopilando datos a medida que avanzas. Sin dominar esto, solo estarás obteniendo un pequeño vistazo de la información disponible.

Identificar y manejar patrones de paginación

Lo primero de todo: tienes que jugar a ser detective. Cada sitio maneja la paginación de forma un poco diferente, así que tienes que inspeccionar la página para entender su método concreto. Normalmente te toparás con uno de estos patrones comunes.

  • Enlaces de botón “Siguiente” clásico: este es el enfoque de toda la vida. Encontrarás un enlace, a menudo etiquetado como “Next” o con un símbolo ” ”, que te lleva a la página siguiente. A veces la URL cambia de forma predecible (como de a ), pero otras veces tendrás que encontrar y extraer el enlace único de la página siguiente.
  • Botones “Cargar más” (Load More): muchos sitios modernos los usan. Cuando haces clic en el botón, usa JavaScript para traer más elementos y añadirlos al final de la página actual, todo sin una recarga completa.
  • Scroll infinito (Infinite Scroll): es similar a un botón “Load More”, pero ocurre automáticamente. A medida que te desplazas hacia abajo, el sitio detecta que estás cerca del final y carga contenido nuevo sobre la marcha.

Para un simple botón “Siguiente”, tu lógica es bastante directa. Scrapearás la página actual, encontrarás el enlace a la siguiente y luego le dirás a tu scraper que lo siga. Puedes envolver todo esto en un bucle que siga ejecutándose mientras exista un botón “Siguiente”.

Cuando te enfrentas a botones “Load More” o scroll infinito, necesitarás recurrir a Playwright o Selenium. Tu script tendrá que actuar como un usuario real: desplazándose hasta el final de la página o haciendo clic repetidamente en ese botón “Load More”. Solo asegúrate de añadir una breve pausa después de cada acción para dar tiempo a que el contenido nuevo se cargue antes de scrapear la página completamente cargada.

Agregar y almacenar tus datos

Una vez que tu scraper salta con éxito de página en página, simplemente imprimir los datos en tu terminal ya no será suficiente. Necesitas una forma sistemática de recopilar toda la información y guardarla en un formato estructurado que realmente puedas usar.

La mejor manera de manejar esto es crear una lista maestra. Dentro de tu bucle de paginación, después de haber extraído los datos de un elemento individual (como el nombre de un producto y su precio), simplemente lo añadirás a tu lista. Me parece mejor almacenar cada elemento como un diccionario, lo que mantiene las cosas limpias y organizadas.

Por ejemplo, tras scrapear un producto, lo añadirías a tu lista así:

Cuando tu bucle finalmente termine, tendrás una lista completa con todos los datos de cada página que visitaste. A partir de ahí, exportarlos es fácil. La biblioteca integrada de Python es perfecta para guardar tus datos en un archivo CSV, que puedes abrir directamente en Excel o Google Sheets. Si tus datos son más complejos o anidados, la biblioteca puede volcar toda tu lista de diccionarios en un archivo JSON con un solo comando.

Para proyectos más grandes y serios, con el tiempo querrás explorar cómo automatizar el web scraping para pipelines de datos escalables, que es el siguiente paso lógico en tu camino de scraping.

Evadir sistemas anti-bot como un profesional

Una vez que tu scraper de Python pasa de unas pocas pruebas a hacer cientos o miles de solicitudes, ya no estás pasando desapercibido. Los sitios web están constantemente al acecho de tráfico que no parece humano, y un simple script disparando solicitudes desde la misma dirección IP es una señal inequívoca. Aquí es donde empieza el verdadero juego del gato y el ratón del web scraping.

En el momento en que empiezas a hacer scraping a cualquier escala real, acabarás chocando contra un muro: un CAPTCHA, un error 403 Forbidden o quizás simplemente una página que devuelve un galimatías sin sentido. Estos no son accidentes; son mecanismos de defensa diseñados para detenerte. El primer paso para construir un scraper resiliente es entender cómo funcionan estos sistemas. Es muy útil familiarizarte con los tipos comunes de ataques de bots y los mecanismos de protección que usan los sitios.

Dominar las defensas básicas

Antes incluso de pensar en tácticas complejas, hay unas cuantas técnicas fundamentales que todo scraper serio necesita. Considéralas el mínimo imprescindible para permanecer oculto. Sin ellas, incluso sitios con protección moderada te cortarán casi de inmediato.

Ante todo, tienes que rotar tu User-Agent. Es una simple cabecera HTTP que tu script envía para identificarse, y el User-Agent por defecto básicamente grita “¡Soy un bot!”. Un enfoque mucho mejor es mantener una lista de User-Agents de navegadores comunes y reales y elegir uno al azar para cada solicitud que hagas.

Otro movimiento crucial es implementar reintentos inteligentes con retroceso exponencial (exponential backoff). Cuando una solicitud falla, no machaques el servidor de nuevo al instante. En su lugar, espera un intervalo corto y aleatorio antes de reintentar. Si falla una segunda vez, duplica ese periodo de espera. Esta estrategia imita la paciencia humana y evita sobrecargar un servidor que quizás solo esté ocupado temporalmente.

Por qué usar solo proxies ya no es suficiente

Durante mucho tiempo, el consejo estándar era sencillo: usa proxies. La lógica era sólida: enruta tus solicitudes a través de diferentes direcciones IP para evitar que te limiten la tasa. Si bien los proxies siguen siendo una parte necesaria del kit de herramientas, ya no son una bala mágica.

Los sistemas anti-bot modernos se han vuelto mucho más inteligentes. No solo comprueban tu dirección IP; analizan toda tu “huella digital”. Esto incluye toda una serie de señales:

  • Huella TLS/JA3: la firma única creada por la forma en que tu cliente inicia una conexión segura.
  • Huella HTTP/2: la configuración y prioridades específicas que tu cliente usa en su conexión HTTP/2.
  • Consistencia de las cabeceras: ¿coinciden realmente tus cabeceras con las de un navegador real? Una cabecera que no concuerda con un User-Agent dado es una clásica señal de alarma.
  • Análisis del comportamiento: ¿estás solicitando páginas más rápido de lo que cualquier humano podría posiblemente leerlas?

Debido a este análisis más profundo, los proxies de centro de datos baratos se detectan casi al instante. Provienen de bloques de IP bien conocidos propiedad de proveedores de nube, y los servicios anti-bot los tienen todos en listas negras. Superar defensas sofisticadas requiere una huella mucho más parecida a la humana.

Comparativa de técnicas de evasión anti-bot

Para sortear estas defensas, tienes varias opciones, cada una con sus propias ventajas y desventajas. La tabla siguiente compara algunas de las técnicas más comunes que he usado a lo largo de los años.

Técnica

Complejidad

Eficacia

Ideal para

Rotación de User-Agent

Baja

Scraping básico en sitios con protección mínima. Un primer paso imprescindible.

Proxies de centro de datos

Baja-Media

Saltarse límites de tasa simples basados en IP. Fácilmente detectados por sistemas avanzados.

Navegadores headless

Media-Alta

Media

Manejar el renderizado de JavaScript, pero aún fácilmente identificables por su huella sin personalización.

IPs residenciales rotativas

Media

Alta

Aparecer como un usuario genuino. Esencial para sitios de comercio electrónico, viajes y redes sociales.

Servicio anti-bot completo

Muy baja

Muy alta

Delegar toda la complejidad (fingerprinting, CAPTCHAs, proxies) para un scraping fiable y a gran escala.

En definitiva, la técnica correcta depende de tu objetivo. Para sitios sencillos, unas cabeceras básicas pueden bastar. Pero para cualquier cosa seria, tendrás que fijarte en las IPs residenciales y, potencialmente, en una solución de servicio completo.

El poder de las IPs residenciales rotativas

Aquí es donde entran en juego las IPs residenciales rotativas. Son direcciones IP reales asignadas por proveedores de servicios de internet (ISP) a hogares reales. Desde la perspectiva de un sitio web, una solicitud desde una IP residencial es indistinguible de una que proviene de un usuario genuino.

Esta técnica es absolutamente vital en sectores como el comercio electrónico, donde las empresas dependen del scraping para la monitorización de precios de la competencia. De hecho, el mercado de datos alternativos, fuertemente impulsado por este tipo de recopilación de datos, está valorado en USD 4.900 millones y crece a un impresionante 28% interanual.

Pero tener simplemente una IP residencial no es la respuesta completa; todavía tienes que resolver el problema del fingerprinting. Por eso muchos de nosotros recurrimos a servicios integrados como ScrapeUnblocker. Combinan proxies residenciales rotativos premium con un fingerprinting avanzado a nivel de navegador que imita dispositivos reales. El servicio se encarga de todo el quebradero de cabeza (rotación de proxies, gestión de cabeceras e incluso resolución de CAPTCHAs), para que tu script pueda centrarse en lo que mejor sabe hacer: extraer datos.

Este diagrama de flujo ofrece una buena visión de la lógica que podrías incorporar a un scraper para manejar algo como la paginación.

Como puedes ver, un scraper inteligente comprueba primero si hay un simple botón Siguiente, luego busca un comportamiento de scroll infinito y finalmente intenta encontrar un botón Cargar más para cubrir los escenarios más comunes.

Preguntas frecuentes sobre web scraping en Python

A medida que te ensucies las manos con el web scraping en Python, seguro que te surgirán preguntas. Es parte del proceso. Quizás te preguntes por las zonas grises legales, o por qué tu scraper, que funcionaba perfectamente ayer, de repente falla.

Esta sección está construida a partir de las preguntas que escucho con más frecuencia de otros desarrolladores. Considéralo tu guía de campo para resolver problemas comunes y tomar mejores decisiones a medida que tus proyectos crecen de simples scripts a operaciones de recopilación de datos más serias.

Esta es la gran pregunta y, sinceramente, la respuesta no es un simple sí o no. Hacer scraping de datos que están disponibles públicamente generalmente está bien, pero eso no significa que sea barra libre. Tienes que ser responsable.

  • Respeta el archivo : antes de escribir una sola línea de código, revisa el archivo del sitio (lo encontrarás en ). Aunque no es un documento jurídicamente vinculante, son las instrucciones explícitas del propietario del sitio web para los bots. Ignorarlo es de mala educación y es la forma más rápida de que bloqueen tu dirección IP.
  • Lee los términos de servicio: los ToS de un sitio son un contrato vinculante. Si dicen explícitamente “prohibido el scraping”, al hacerlo estás violando ese contrato, lo que podría meterte en problemas legales. Léelos siempre antes de comprometerte con un proyecto grande.
  • No toques datos personales: esta es una línea roja importante. Regulaciones como el RGPD europeo y la CCPA de California tienen penalizaciones severas por recopilar información de identificación personal (PII) sin consentimiento. Scrapear nombres, correos electrónicos o números de teléfono es buscarse problemas.
  • No machaques el servidor: disparar cientos de solicitudes por minuto puede ralentizar un sitio o incluso hacerlo caer. Esto puede parecerse mucho a un ataque de denegación de servicio (DoS), y los administradores del sitio no estarán contentos. Incorpora siempre retardos para hacer scraping a un ritmo razonable y similar al humano.

En caso de duda, especialmente si haces scraping para un proyecto comercial, consulta con un abogado. Ser un scraper ético no se trata solo de evitar un bloqueo: se trata de ser un buen ciudadano de la web.

¿Cómo elijo entre BeautifulSoup y Playwright?

La herramienta adecuada para el trabajo depende realmente de con qué está construido el sitio web objetivo. Elegir mal aquí es una receta para el dolor de cabeza.

El stack clásico de Requests y BeautifulSoup es fantástico para sitios web simples y estáticos. La prueba es fácil: haz clic derecho y “Ver código fuente de la página” en tu navegador. Si todos los datos que necesitas están ahí mismo, en el HTML en bruto, esta combinación es tu mejor apuesta. Es ligera, rápida y suave con los recursos de tu sistema.

Pero ¿qué pasa si el contenido que quieres solo aparece después de desplazarte o hacer clic en algo? Eso es JavaScript en acción, y es increíblemente común en sitios de comercio electrónico, feeds de redes sociales y aplicaciones web modernas. Para estos, necesitas una herramienta completa de automatización de navegador. Mi favorita para esto es Playwright. Conduce un navegador real, permitiendo que tu script espere a que todo ese contenido dinámico se cargue antes de intentar capturar nada.

¿Cuál es la mejor forma de almacenar los datos scrapeados?

No existe una única “mejor” forma de almacenar tus datos; depende completamente de cómo sean los datos y de qué planeas hacer con ellos.

Para trabajos pequeños y sencillos, donde los datos son planos, un archivo CSV (valores separados por comas) es perfecto. Es el lenguaje universal de los datos y puede abrirse con prácticamente cualquier cosa, incluidos Excel o Google Sheets, para un análisis rápido.

Si tus datos son más complejos o anidados (piensa en una página de producto con múltiples variantes, cada una con su propio precio, color y nivel de stock), entonces JSON (JavaScript Object Notation) es una opción mucho mejor. Está diseñado para manejar ese tipo de estructura jerárquica, lo que te facilita mucho la vida cuando necesitas parsearlo después.

Para cualquier proyecto de scraping a gran escala o de larga duración, querrás usar una base de datos en condiciones. Es la única forma de gestionar, consultar y actualizar grandes volúmenes de datos de forma eficiente. Una base de datos relacional como PostgreSQL es estupenda para datos estructurados, mientras que una base de datos NoSQL como MongoDB encaja mejor si tus datos están menos estructurados o es probable que cambien de forma con el tiempo.

Prueba ScrapeUnblocker gratis

Tasa de éxito del 99%+ · desde 0,55 € por cada 1000 llamadas · 500 solicitudes gratis al registrarte.

Pruébalo gratis → Ver precios