---
title: "Cómo extraer datos de Booking.com con Python"
slug: how-to-scrape-booking
date: 2026-02-23T09:53:54+00:00
modified: 2026-02-23T09:53:55+00:00
permalink: https://brightdata.es/blog/datos-web/how-to-scrape-booking
type: blog
---

[ Blog ](https://brightdata.es/blog "Blog") / [Datos web](https://brightdata.es/blog/datos-web)







 [Datos web](https://brightdata.es/blog/datos-web)

# Cómo extraer datos de Booking.com con Python

Aprenda a crear un Scraper en Python para Booking.com con el fin de extraer datos de hoteles, reseñas y precios de manera eficiente.

 22 min de lectura





 [ ![Antonello Zanini](https://media.brightdata.es/2022/12/Antonello-Zanini-2-50x50.jpg) ](https://brightdata.com/blog/authors/antonello-zanini)

 [Antonello Zanini

Technical Writer

 ](https://brightdata.com/blog/authors/antonello-zanini)





 ![How to Scrape Booking.com With Python blog image](https://media.brightdata.es/2024/11/How-to-Scrape-Booking.com-With-Python_.svg)





En este tutorial, verás:

- La definición de un Scraper de reservas
- Qué datos se pueden extraer con él
- Cómo crear un script de scraping de Booking.com con Python

¡Empecemos!

## <a></a>¿Qué es un Scraper de Booking?

[Un scraper de Booking.com](/products/web-scraper/booking) es una herramienta que extrae automáticamente datos de las páginas de Booking.com. Te permite recuperar información de las páginas de listados de propiedades, como nombres de hoteles, precios, reseñas, valoraciones, servicios y disponibilidad. Estos datos se pueden utilizar para diversos fines, como análisis de mercado, comparación de precios y creación de Conjuntos de datos relacionados con los viajes.

## Datos que se pueden extraer de Booking.com

A continuación se muestra una lista de los puntos de datos que puedes recuperar de Booking.com:

- **Detalles del establecimiento**: nombre del hotel, dirección, distancia a puntos de referencia (por ejemplo, centro de la ciudad, centro comercial, etc.).
- **Información sobre precios**: precio normal, precio con descuento (si está disponible).
- **Opiniones y valoraciones**: puntuación de las opiniones, número de opiniones, comentarios de los huéspedes
- **Disponibilidad**: tipos de habitaciones disponibles, opciones de reserva (por ejemplo, cancelación gratuita, desayuno incluido), fechas con disponibilidad
- **Medios**: Imágenes del establecimiento, imágenes de las habitaciones
- **Servicios**: instalaciones ofrecidas (por ejemplo, wifi, aparcamiento, piscina), servicios específicos de las habitaciones
- **Promociones**: ofertas especiales o descuentos, ofertas por tiempo limitado
- **Políticas**: política de cancelación, horarios de entrada y salida
- **Detalles adicionales**: descripción del establecimiento, atracciones cercanas, número de habitaciones disponibles para fechas específicas

## Extracción de datos de Booking.com en Python: guía paso a paso

En esta sección guiada, aprenderás a crear un Scraper de Booking.com.

El objetivo es crear un script en Python que recopile automáticamente los datos de la página de listado de propiedades:

![Property listing page example](https://media.brightdata.es/2024/11/image-63.png)¡Sigue los pasos que se indican a continuación!

### <a></a>Paso n.º 1: Configuración del proyecto

Antes de empezar, asegúrate de tener Python 3 instalado en tu ordenador. Si no es [así, descárgalo](https://www.python.org/downloads/), ejecuta el archivo ejecutable y sigue las instrucciones del asistente de instalación.

Ahora, utiliza los siguientes comandos para crear una carpeta para tu proyecto:

```none
mkdir booking-scraper

```

El directorio `booking-scraper` representa la carpeta del proyecto de su script de scraping de Python Booking.com.

Entra en él e inicializa un [entorno virtual](https://docs.python.org/3/library/venv.html) dentro de él:

```none
cd booking-Scraper
python -m venv env

```

Cargue la carpeta del proyecto en su IDE de Python favorito. [Visual Studio Code con la extensión Python](https://code.visualstudio.com/docs/languages/python) y [PyCharm Community Edition](https://www.jetbrains.com/pycharm/download/#section=windows) son dos excelentes opciones.

Crea un archivo `scraper.py` en la carpeta del proyecto, que debe contener esta estructura de archivos:

![A scraper.py file in the project folder](https://media.brightdata.es/2024/11/image-64.png)`scraper.py` es ahora un script Python en blanco, pero pronto contendrá la lógica de scraping.

En la terminal del IDE, activa el entorno virtual. Para ello, en Linux o macOS, ejecuta este comando:

```none
./env/bin/activate

```

De forma equivalente, en Windows, ejecuta:

```none
env/Scripts/activate

```

¡Genial, ahora tienes un entorno Python para el Scraping web!

### <a></a>Paso n.º 2: selecciona la biblioteca de scraping

Es hora de determinar si Booking.com es un sitio estático o dinámico y seleccionar la biblioteca de scraping adecuada en consecuencia. Esto se puede hacer inspeccionando el comportamiento del sitio. Empieza abriendo Booking.com en tu navegador. Realiza una búsqueda y navega hasta la página de la propiedad:

![search and navigate to the property page](https://media.brightdata.es/2024/11/image-65.png)Observe que la página carga nuevos datos dinámicamente a medida que se desplaza hacia abajo:

![New data loaded dynamically as you scroll down](https://media.brightdata.es/2024/11/image-66.png)Ese patrón se conoce como *desplazamiento infinito* y es un sello distintivo de los sitios dinámicos. Obtén más información sobre cómo [realizar Scraping web en sitios dinámicos](/blog/how-tos/scrape-dynamic-websites-python).

Sin siquiera profundizar en el código HTML del documento devuelto por el servidor o inspeccionar la pestaña *Red* en DevTools (dos pasos comunes para comprender si un sitio es estático o no), ya podemos concluir que Booking.com es un sitio dinámico.

El mejor enfoque para extraer datos de un sitio de contenido dinámico es utilizar una [herramienta de automatización del navegador](/blog/web-data/best-headless-browsers). Estas soluciones le permiten controlar un navegador y realizar interacciones específicas en la página para extraer datos de forma eficaz.

Una de las herramientas de automatización de navegadores más potentes para Python es [Selenium](https://www.selenium.dev/), lo que la convierte en una excelente opción para extraer datos de Booking.com. Prepárate para instalarla, ya que será la biblioteca principal para esta tarea.

### <a></a>Paso n.º 3: Instalar y configurar Selenium

En Python, Selenium está disponible a través del paquete pip [`selenium`](https://pypi.org/project/selenium/). En un entorno virtual Python activado, instálalo con este comando:

```none
pip install selenium

```

Para obtener orientación sobre cómo utilizar la herramienta, lee nuestro tutorial sobre [Scraping web con Selenium](/blog/how-tos/using-selenium-for-web-scraping).

Importa Selenium en `scraper.py` e inicializa un objeto `WebDriver` para controlar una instancia de Chrome:

```none
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# crear una instancia del controlador web Chrome
driver = webdriver.Chrome(service=Service())

```

El código anterior inicializa una instancia [de Chrome `WebDriver`](https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.chrome.webdriver) para controlar un navegador Chrome. Ten en cuenta que Booking.com parece utilizar tecnología antirraspado que bloquea los navegadores sin interfaz gráfica. Por lo tanto, evita establecer el indicador [`--headless`](https://developer.chrome.com/docs/chromium/headless). Como solución alternativa, lee nuestra guía sobre [Playwright Stealth](/blog/how-tos/avoid-bot-detection-with-playwright-stealth).

Como última línea de su Scraper, recuerde cerrar el controlador web:

```none
driver.quit()

```

¡Genial! Ya tienes todo configurado para empezar a extraer datos de Booking.com.

### <a></a>Paso n.º 4: Visita la página de destino

Las páginas de Booking.com ofrecen numerosas funciones interactivas para refinar su búsqueda:

![interactive features to refine your search](https://media.brightdata.es/2024/11/image-67.png)Simular todas estas interacciones mediante programación con Selenium sería complejo y llevaría mucho tiempo. Por lo tanto, para simplificar y acelerar el proceso, primero realiza las interacciones manualmente en tu navegador.

Una vez que haya configurado la consulta de búsqueda que le interesa, copie la URL de la página resultante de la barra de direcciones de su navegador.

Por ejemplo, la URL anterior representa una búsqueda de apartamentos en Nueva York del 18 de noviembre al 18 de diciembre para dos adultos.

Copie la URL e introdúzcala en el método [`get()`](https://selenium-python.readthedocs.io/api.html#selenium.webdriver.remote.webdriver.WebDriver.get) que ofrece Selenium:

```none
driver.get("https://www.booking.com/searchresults.html?ss=New+York&ssne=New+York&ssne_untouched=New+York&label=gen173nr-1FCAEoggI46AdIM1gEaHGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4Aof767kGwAIB0gIkNGE2MTI1MjgtZjJlNC00YWM4LWFlMmQtOGIxZjM3NWIyNDlm2AIF4AIB&sid=b91524e727f20006ae00489afb379d3a&aid=304142&lang=en-us&sb=1&src_elem=sb&src=index&dest_id=20088325&dest_type=city&checkin=2024-11-18&checkout=2024-12-18&group_adults=2&no_rooms=1&group_children=0")

```

Tu script de scraping se conectará automáticamente a la página deseada de Booking.com.

El archivo `scraper.py` ahora contendrá estas líneas de código:

```none
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# crear una instancia del controlador web Chrome
driver = webdriver.Chrome(service=Service())

# conectarse a la página de destino
driver.get("https://www.booking.com/searchresults.html?ss=New+York&ssne=New+York&ssne_untouched=New+York&label=gen173nr-1FCAEoggI46AdIM1gEaHGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4Aof767kGwAIB0gIkNGE2MTI1MjgtZjJlNC00YWM4LWFlMmQtOGIxZjM3NWIyNDlm2AIF4AIB&sid=b91524e727f20006ae00489afb379d3a&aid=304142&lang=en-us&sb=1&src_elem=sb&src=index&dest_id=20088325&dest_type=city&checkin=2024-11-18&checkout=2024-12-18&group_adults=2&no_rooms=1&group_children=0")

# lógica de scraping...

# cerrar el controlador web y liberar sus recursos
driver.quit()

```

Coloca un punto de interrupción de depuración en la última línea y ejecuta el script. A continuación se muestra lo que deberías ver:

![Example of what you should see after you run the script](https://media.brightdata.es/2024/11/image-68.png)El mensaje «Chrome está siendo controlado por un software de pruebas automatizado» certifica que Selenium está funcionando en Chrome como se desea. ¡Bien hecho!

### <a></a>Paso n.º 5: gestionar la alerta de inicio de sesión

Cuando visita Booking.com por primera vez en un navegador, el sitio suele mostrar una alerta de inicio de sesión en los primeros 20 segundos. Esto bloquea el acceso al contenido de la página, lo que dificulta el Scraping web:

![a sign-in alert within the first 20 seconds](https://media.brightdata.es/2024/11/image-69.png)Hasta que no interactúes con ella, no podrás acceder al contenido de la página subyacente.

Para gestionar la alerta, ciérrela con Selenium. Haga clic con el botón derecho del ratón en el botón de cierre y seleccione la opción «Inspeccionar» en el menú contextual:

![Right-click on the close button](https://media.brightdata.es/2024/11/image-70.png)Ten en cuenta que puedes cerrar el modal seleccionando el botón con el siguiente selector CSS:

```none
[role="dialog"] button[aria-label="Dismiss sign-in info."]

```

Ahora, indica a Selenium que espere hasta 10 segundos a que aparezca la alerta. Una vez que aparezca, ciérrala haciendo clic en el botón de descartar. Dado que el modal puede no aparecer siempre, tiene sentido envolver esta lógica en un bloque [`try...except`](https://docs.python.org/3/tutorial/errors.html):

```none
try:
    # esperar hasta 20 segundos a que aparezca la alerta de inicio de sesión
    close_button = WebDriverWait(driver, 20).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "[role="dialog"] button[aria-label="Dismiss sign-in info."]"))
    )
    # hacer clic en el botón Cerrar
    close_button.click()
except TimeoutException:
    print("El modal de inicio de sesión no apareció, continuando...")

```

[`WebDriverWait`](https://selenium-python.readthedocs.io/waits.html#explicit-waits) es una clase especializada de Selenium que pausa el script hasta que se cumple una condición específica en la página. En el ejemplo anterior, espera hasta 10 segundos a que aparezca el botón de cierre de la alerta en la página.

Si la alerta no aparece, Selenium genera la excepción `TimeoutException`. Importe junto con `WebDriverWait`, `EC` y `By` como se muestra a continuación:

```none
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException

```

¡Genial! La alerta de inicio de sesión ya no es un problema.

### Paso n.º 6: Selecciona los elementos de Booking.com

Ten en cuenta que la página de Booking.com que se va a extraer contiene varios elementos. Como quieres extraerlos todos, inicializa una matriz donde almacenar los datos extraídos:

```none
items = []

```

Ahora, debe comprender cómo seleccionar los elementos HTML asociados a esos elementos. Abra Booking.com en su navegador, realice una búsqueda e inspeccione uno de los elementos de la propiedad:

![Open Booking.com in your browser, perform a search, and inspect one of the property items](https://media.brightdata.es/2024/11/image-71.png)Observe que las clases de los elementos HTML parecen generarse aleatoriamente. Esto significa que es probable que cambien con cada implementación del sitio, lo que los hace poco fiables para la selección de elementos. En su lugar, céntrese en atributos más estables como `data-testid`.

Los atributos`data-*` son excelentes objetivos para el Scraping web.

Utilice el método [`find_elements()`](https://selenium-python.readthedocs.io/locating-elements.html) de Selenium para aplicar un selector CSS en la página y seleccionar los elementos de interés:

```none
property_items = driver.find_elements(By.CSS_SELECTOR, "[data-testid="property-card"]")

```

Itere sobre los elementos de la propiedad y prepare su Scraper de Booking.com para extraer algunos datos:

```none
for property_item in property_items:
    # lógica de scraping...

```

¡Genial! El siguiente paso es extraer datos de estos elementos.

### Paso n.º 7: extraer los elementos de Booking.com

Echa un vistazo a los elementos de la propiedad en la página y observa que los elementos que contienen son inconsistentes:

![the property items on the page](https://media.brightdata.es/2024/11/image-72.png)Algunos tienen una puntuación de reseñas, mientras que otros no. De nuevo, algunos tienen un precio con descuento, mientras que otros no.

Estas diferencias dificultan la escritura de una lógica de scraping coherente para todos los elementos de propiedad. Cuando intentas seleccionar un elemento que no está en la página, Selenium genera una `excepción NoSuchElementException`. Por lo tanto, tiene sentido definir una función para manejar ese escenario:

```none
def handle_no_such_element_exception(data_extraction_task):
    try:
        return data_extraction_task()
    except NoSuchElementException as e:
        return None

```

La función anterior acepta una función lambda e intenta ejecutarla. Si genera una `excepción NoSuchElementException`, la captura y devuelve `None`. Esto permite que el script de scraping de Booking.com continúe sin interrupciones.

Importar `NoSuchElementException`:

```none
from selenium.common import NoSuchElementException

```

Inspeccione un elemento de propiedad que contenga todos los elementos (puntuación de la reseña, precio con descuento, etc.):

![Inspecting a property item](https://media.brightdata.es/2024/11/image-73.png)Tenga en cuenta que puede extraer:

- El enlace de la propiedad desde `a[data-testid="property-card-desktop-single-image"]`
- La imagen de la propiedad desde `img[data-testid=image]`

En el bucle `«for»`, aplique la lógica actual para seleccionar esos elementos y extraer datos de ellos:

```none
url = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "a[data-testid="property-card-desktop-single-image"]").get_attribute("href"))
image = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "img[data-testid="image"]").get_attribute("src"))

```

`find_element()` selecciona un único nodo de la página, mientras que `get_attribute()` obtiene el contenido dentro del atributo HTML especificado. Tenga en cuenta que las instrucciones de extracción de datos están envueltas por `handle_no_such_element_exception` para gestionar `NoSuchElementExceptions`.

Del mismo modo, céntrese en la información de la sección del título y justo debajo de ella:

![focus on the information in the title section and below it](https://media.brightdata.es/2024/11/image-74.png)Aquí, puede obtener:

- El título de la propiedad de `[data-testid="title"]`
- La propiedad dirección de `[data-testid="address"]`
- La propiedad distance de `[data-testid="distance"]`

Recopílelos todos con:

```none
title = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="title"]").text)
address = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="address"]").text)
distance = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="distance"]").text)

```

El atributo `text` contiene el texto dentro de los elementos seleccionados.

A continuación, concéntrese en el nodo de puntuación de la reseña:

![review score node](https://media.brightdata.es/2024/11/image-75.png)Selecciónelo con `data-testid="review-score"` y extraiga su texto. Tenga en cuenta que el texto tiene un formato especial, como en este ejemplo:

```none
«Puntuación 8,4n8,4nMuy buenon120 reseñas»

```

Con algo de lógica personalizada, puede extraer la puntuación de la reseña y el recuento de reseñas:

```none
puntuación_de_la_reseña = Ninguna
número_de_reseñas = Ninguno
texto_de_la_reseña = manejar_excepción_elemento_no_encontrado(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="puntuación-de-la-reseña"]").texto)
si texto_de_la_reseña no es Ninguno:
  # dividir la cadena de la reseña por n
  partes = texto_de_la_reseña.split("n")

  # procesar cada parte
  for part in parts:
      part = part.strip()
      # comprobar si esta parte es un número (puntuación potencial de la reseña)
      if part.replace(".", "", 1).isdigit():
          review_score = float(part)
      # comprueba si contiene la cadena «reviews»
      elif «reviews» in part:
          # extrae el número antes de «reviews»
          review_count = int(part.split(" ")[0].replace(«,», »))

```

Selecciona el elemento de descripción:

![The description element](https://media.brightdata.es/2024/11/image-76.png)Seleccionarlo con `data-testid="recommended-units"` y extraer la descripción:

```none
description = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="recommended-units"]").text)

```

Por último, céntrate en los elementos de precio:

![The price element](https://media.brightdata.es/2024/11/image-77.png)Desde el elemento `data-testid="availability-rate-information"`, selecciona:

- El precio original del nodo que tiene el atributo `aria-hidden="true"` y no tiene el atributo `data-testid`
- El precio con descuento/actual de `data-testid="price-and-discounted-price"`

Escriba la lógica de extracción de precios como se indica a continuación:

```none
price_element = handle_no_such_element_exception(lambda: (property_item.find_element(By.CSS_SELECTOR, "[data-testid="availability-rate-information"]")))
if price_element is not None:
    original_price = handle_no_such_element_exception(lambda: (
        price_element.find_element(By.CSS_SELECTOR, "[aria-hidden="true"]:not([data-testid])").text.replace(",", "")
    ))
    price = handle_no_such_element_exception(lambda: (
        price_element.find_element(By.CSS_SELECTOR, "[data-testid="price-and-discounted-price"]").text.replace(",", "")
    ))

```

¡Vaya! La lógica de scraping de Booking.com está casi completa.

### <a></a>Paso n.º 7: recopilar los datos extraídos

Ahora tienes los datos extraídos repartidos en varias variables dentro del bucle `«for` ». Crea un nuevo objeto `«item»`, rellénalo con esos datos y añádelo a la matriz `«items` »:

```none
item = {
  "url": url,
  "image": image,
  "title": title,
  "address": address,
  "distance": distance,
  "review_score": review_score,
  "review_count": review_count,
  "description": description,
  "original_price": original_price,
  "price": price
}
items.append(item)

```

Al final del bucle `«for»`, `«items»` contendrá todos los datos extraídos. Compruébelo imprimiendo `«items»:`

```none
print(items)

```

Esto producirá el siguiente resultado:

```none
[{'url': 'https://www.booking.com/hotel/us/murray-hill-east-manhattan.html?label=gen173nr-1FCAEoggI46AdIM1gEaHGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4Aof767kGwAIB0gIkNGE2MTI1MjgtZjJlNC00YWM4LWFlMmQtOGIxZjM3NWIyNDlm2AIF4AIB&sid=b91524e727f20006ae00489afb379d3a&aid=304142&ucfs=1&arphpl=1&checkin=2024-11-18&checkout=2024-12-18&dest_id=20088325&dest_type=city&group_adults=2&req_adults=2&no_rooms=1&group_children=0&req_children=0&hpos=1&hapos=1&sr_order=popularity&srpvid=c6926559ebaa0862&srepoch=1731939905&all_sr_blocks=5604802_204869446_2_0_0&highlighted_blocks=5604802_204869446_2_0_0&matching_block_id=5604802_204869446_2_0_0&sr_pri_blocks=5604802_204869446_2_0_0__523000&from=searchresults', 'image': 'https://cf.bstatic.com/xdata/images/hotel/square600/84564452.webp?k=ff50b7387e08e01ba7a400effa788e668f894cabe4a295f60d6cd018ec9ac4d0&o=', 'title': 'Murray Hill East Suites', 'address': 'Murray Hill, Nueva York', 'distance': «1,3 millas del centro», «puntuación»: 8,2, «número de reseñas»: 54, «descripción»: «EstudioEstudio completo • 1 baño • 1 cocina • 398 pies cuadradosnVarios tipos de camas», «precio original»: Ninguno, «precio»: «5230 $»},
# omitido por brevedad...
, {'url': 'https://www.booking.com/hotel/us/renaissance-times-square.html?label=gen173nr-1FCAEoggI46AdIM1gEaHGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4Aof767kGwAIB0gIkNGE2MTI1MjgtZjJlNC00YWM4LWFlMmQtOGIxZjM3NWIyNDlm2AIF4AIB&sid=b91524e727f20006ae00489afb379d3a&aid=304142&ucfs=1&arphpl=1&checkin=2024-11-18&checkout=2024-12-18&dest_id=20088325&dest_type=city&group_adults=2&req_adults=2&no_rooms=1&group_children=0&req_children=0&hpos=12&hapos=12&sr_order=popularity&srpvid=c6926559ebaa0862&srepoch=1731939905&all_sr_blocks=2315604_274565698_0_2_0&highlighted_blocks=2315604_274565698_0_2_0&matching_block_id=2315604_274565698_0_2_0&sr_pri_blocks=2315604_274565698_0_2_0__1805400&from_sustainable_property_sr=1&from=searchresults', 'image': 'https://cf.bstatic.com/xdata/images/hotel/square600/437371642.webp?k=d1a06036e365573e326e6b0f1b045f8f43b6ad0d18e119cfb92d92cc81fa5c88&o=', 'title': 'Renaissance New York Times Square by Marriott', 'address': 'Manhattan, Nueva York', 'distance': '0,6 millas del centro', 'review_score': 8,4, 'review_count': 2209, 'description': 'Habitación King con 1 cama king size', 'original_price': '20060 $', 'price': '18054 $'}]

```

¡Fantástico! Solo queda exportar esta información a un archivo legible para humanos, como CSV.

### <a></a>Paso n.º 8: Exportar a CSV

Importa el paquete [`csv`](https://docs.python.org/3/library/csv.html) de la biblioteca estándar de Python:

```none
import csv

```

A continuación, utilícelo para exportar `elementos` a un archivo CSV:

```none
# especifique el nombre del archivo CSV de salida
archivo_salida = "propiedades.csv"

# exporte la lista de elementos a un archivo CSV
con open(archivo_salida, modo="w", nueva_línea="", codificación="utf-8") como archivo:
    #crear un objeto escritor CSV
    writer = csv.DictWriter(file, fieldnames=["url", "image", "title", "address", "distance", "review_score", "review_count", "description", "original_price", "price"])

    # escribir la fila del encabezado
    writer.writeheader()

    # escribir cada elemento como una fila en el CSV
    writer.writerows(items)

```

Este fragmento de código rellena un archivo CSV llamado `properties.csv` utilizando datos de las matrices `de elementos`. Las funciones clave utilizadas anteriormente son:

- [`open()`](https://docs.python.org/3/library/functions.html#open): Abre el archivo especificado en modo de escritura con codificación UTF-8.
- [`csv.DictWriter()`](https://docs.python.org/3/library/csv.html#csv.DictWriter): Crea un escritor CSV con los nombres de campo dados.
- `writeheader()`: Escribe la fila de encabezado en el archivo CSV basándose en los nombres de campo especificados.
- `writer.writerow()`: Escribe cada elemento del diccionario como una fila en el CSV.

### <a></a>Paso n.º 9: Juntarlo todo

`scraper.py` ahora debería contener estas líneas:

```none
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.common import NoSuchElementException

import csv

def handle_no_such_element_exception(data_extraction_task):
    try:
        return data_extraction_task()
    except NoSuchElementException as e:
        return None

# crear una instancia del controlador web Chrome
driver = webdriver.Chrome(service=Service())

# conectarse a la página de destino
driver.get("https://www.booking.com/searchresults.html?ss=New+York&ssne=New+York&ssne_untouched=New+York&label=gen173nr-1FCAEoggI46AdIM1gEaHGIAQGYATG4ARfIAQzYAQHoAQH4AQKIAgGoAgO4Aof767kGwAIB0gIkNGE2MTI1MjgtZjJlNC00YWM4LWFlMmQtOGIxZjM3NWIyNDlm2AIF4AIB&sid=b91524e727f20006ae00489afb379d3a&aid=304142&lang=en-us&sb=1&src_elem=sb&src=index&dest_id=20088325&dest_type=city&checkin=2024-11-18&checkout=2024-12-18&group_adults=2&no_rooms=1&group_children=0")

# gestionar la alerta de inicio de sesión
try:
    # esperar hasta 20 segundos a que aparezca la alerta de inicio de sesión
    close_button = WebDriverWait(driver, 20).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "[role="dialog"] button[aria-label="Dismiss sign-in info."]"))
    )
    # hacer clic en el botón Cerrar
    close_button.click()
except e:
    print("No apareció el modal de inicio de sesión, continuando...")

# dónde almacenar los datos extraídos
items = []

# seleccionar todos los elementos de la propiedad en la página
property_items = driver.find_elements(By.CSS_SELECTOR, "[data-testid="property-card"]")

# iterar sobre los elementos de la propiedad y
# extraer datos de ellos
for property_item in property_items:
    # lógica de extracción...
    url = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "a[data-testid="property-card-desktop-single-image"]").get_attribute("href"))
    image = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "img[data-testid="image"]").get_attribute("src"))

    title = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="title"]").text)
    address = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="address"]").text)
    distance = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="distance"]").text)

    review_score = None
    review_count = None
    review_text = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="review-score"]").text)
    if review_text is not None:
      # divide la cadena de la reseña por n
      parts = review_text.split("n")

      # procesar cada parte
      for part in parts:
          part = part.strip()
          # comprobar si esta parte es un número (puntuación potencial de la reseña)
          if part.replace(".", "", 1).isdigit():
              review_score = float(part)
          # comprobar si contiene la cadena «reviews»
          elif «reviews» in part:
              # extraer el número antes de «reviews»
              review_count = int(part.split(" ")[0].replace(",", ""))

    decription = handle_no_such_element_exception(lambda: property_item.find_element(By.CSS_SELECTOR, "[data-testid="recommended-units"]").text)

    price_element = handle_no_such_element_exception(lambda: (property_item.find_element(By.CSS_SELECTOR, "[data-testid="availability-rate-information"]")))
    if price_element is not None:
        original_price = handle_no_such_element_exception(lambda: (
            price_element.find_element(By.CSS_SELECTOR, "[aria-hidden="true"]:not([data-testid])").text.replace(",", "")
        ))
        price = handle_no_such_element_exception(lambda: (
            price_element.find_element(By.CSS_SELECTOR, "[data-testid="price-and-discounted-price"]").text.replace(",", "")
        ))

    # rellenar un nuevo elemento con los datos extraídos
    elemento = {
      "url": url,
      "imagen": imagen,
      "título": título,
      "dirección": dirección,
      "distancia": distancia,
      "review_score": review_score,
      "review_count": review_count,
      "decription": decription,
      "original_price": original_price,
      "price": price
    }
    # añadir el nuevo elemento a la lista de elementos extraídos
    items.append(item)

# especificar el nombre del archivo CSV de salida
archivo_salida = "propiedades.csv"

# exportar la lista de elementos a un archivo CSV
con open(archivo_salida, modo="w", nueva_línea="", codificación="utf-8") como archivo:
    #crear un objeto escritor CSV
    writer = csv.DictWriter(file, fieldnames=["url", "image", "title", "address", "distance", "review_score", "review_count", "decription", "original_price", "price"])

    # escribir la fila del encabezado
    writer.writeheader()

    # escribir cada elemento como una fila en el CSV
    writer.writerows(items)

# cerrar el controlador web y liberar sus recursos
driver.quit()

```

¿Te lo puedes creer? En solo unas 110 líneas, acabas de crear un Scraper de Python para Booking.com.

Comprueba que funciona ejecutando el script de rastreo. En Windows, ejecuta el Scraper con:

```none
python Scraper.py

```

De forma equivalente, en Linux o macOS, ejecuta:

```none
python3 Scraper.py

```

Espera a que el script termine de ejecutarse. Aparecerá un archivo `properties.csv` en el directorio raíz de tu proyecto. Abre el archivo para ver los datos extraídos:

![A properties.csv file with all the extracted data](https://media.brightdata.es/2024/11/image-78.png)¡Enhorabuena, misión completada!

## <a></a>Conclusión

En este tutorial, ha aprendido qué es un Scraper de Booking.com y cómo crear uno utilizando Python. Como se ha mostrado, crear un script básico para recuperar automáticamente datos de Booking.com solo requiere unas pocas líneas de código.

Sin embargo, el ejemplo que se presenta aquí no aborda muchos de los retos que puedes encontrar al extraer datos de Booking.com. Problemas como las medidas contra los navegadores sin interfaz gráfica, el manejo de las interacciones de los usuarios para generar resultados de búsqueda y el desplazamiento infinito pueden complicar rápidamente tus operaciones de extracción.

¿Buscas una solución de scraping más fácil, completa y potente? ¡Prueba [la API Booking Scraper de Bright Data](/products/web-scraper/booking)!

La API Booking Scraper proporciona potentes puntos finales para extraer datos públicos de hoteles, reseñas, valoraciones y mucho más. Con simples llamadas a la API, puede recuperar datos en formatos JSON o HTML.

¿Prefiere soluciones preconstruidas? ¡Bright Data también ofrece [Conjuntos de datos de Booking.com listos para usar](/products/datasets/booking)!

Crea hoy mismo una cuenta gratuita en Bright Data para probar nuestras API de Scraper o explorar nuestros Conjuntos de datos.



Contactar ventasPrueba gratuita![google social icon](/wp-content/themes/brightdata/assets/images/ic_google.svg)









 Tabla de Contenidos







Booking Scraper

Easily scrape Booking with our Booking Scraper API or No-Code Scraper.

Start free trial

Booking Dataset

Skip scraping, purchase a Booking dataset.

Get dataset







 [ ](https://news.ycombinator.com/submitlink?t=C%C3%B3mo+extraer+datos+de+Booking.com+con+Python&u=https://brightdata.es/blog/datos-web/how-to-scrape-booking) [ ](https://www.linkedin.com/shareArticle?mini=true&title=C%C3%B3mo+extraer+datos+de+Booking.com+con+Python&url=https://brightdata.es/blog/datos-web/how-to-scrape-booking) [ ](http://www.reddit.com/submit?title=C%C3%B3mo+extraer+datos+de+Booking.com+con+Python&url=https://brightdata.es/blog/datos-web/how-to-scrape-booking)







##  Usted también puede estar interesado en

 [ ![OpenHuman with Bright Data](https://media.brightdata.es/2026/09/OpenHuman-with-Bright-Data.png) ](https://brightdata.es/blog/ai/openhuman-with-bright-data "Acceso Web Listo para Producción en OpenHuman a Través de la CLI de Bright Data")

 [AI



 ![Antonello Zanini](https://media.brightdata.es/2022/12/Antonello-Zanini-2-50x50.jpg)

Antonello Zanini

Technical Writer





### Acceso Web Listo para Producción en OpenHuman a Través de la CLI de Bright Data

Integra la CLI de Bright Data con OpenHuman para habilitar acceso web listo para producción y recopilación de datos para agentes de IA.



 09-Sep-2026

 14 min de lectura

 ](https://brightdata.es/blog/ai/openhuman-with-bright-data)

 [ ![Multimodal Web Scraping with MiniMax](https://media.brightdata.es/2026/09/Multimodal-Web-Scraping-with-MiniMax.png) ](https://brightdata.es/blog/datos-web/multimodal-web-scraping-with-minimax "Scraping Web Multimodal con MiniMax")

 [Datos web



 ![Antonello Zanini](https://media.brightdata.es/2022/12/Antonello-Zanini-2-50x50.jpg)

Antonello Zanini

Technical Writer





### Scraping Web Multimodal con MiniMax

Combina Bright Data Web Unlocker con la visión de MiniMax M3 para extraer datos estructurados de imágenes y capturas de pantalla de páginas web.



 09-Sep-2026

 5 min de lectura

 ](https://brightdata.es/blog/datos-web/multimodal-web-scraping-with-minimax)

 [ ![The 10 Best CLI Tools for Codex in 2026](https://media.brightdata.es/2026/08/The-10-Best-CLI-Tools-for-Codex-in-2026.png) ](https://brightdata.es/blog/ai/best-cli-tools-for-codex "Las 10 mejores herramientas CLI para Codex en 2026 – Probadas y clasificadas")

 [AI



 ![Daniel Shashko](https://media.brightdata.es/2022/04/Daniel-Shashko-2-50x50.png)

Daniel Shashko

Web Data &amp; AI Expert





### Las 10 mejores herramientas CLI para Codex en 2026 – Probadas y clasificadas

Las 10 herramientas CLI que hacen a Codex más rápido y capaz, comenzando con la Bright Data CLI para acceso web real desde dentro del sandbox.



 06-Sep-2026

 24 min de lectura

 ](https://brightdata.es/blog/ai/best-cli-tools-for-codex)
