Volver al blog
Guías
Raluca PenciucLast updated on Mar 31, 20266 min read

Aprovecha todo el potencial de los datos: cómo extraer información valiosa de Booking.com

Aprovecha todo el potencial de los datos: cómo extraer información valiosa de Booking.com

Como agencia de viajes online líder, Booking.com es una mina de datos valiosos sobre hoteles y alojamientos vacacionales de todo el mundo. Desde opiniones de huéspedes hasta precios y disponibilidad, la información disponible en Booking puede resultar increíblemente útil para una amplia variedad de fines.

Tanto si eres propietario de un negocio que evalúa a la competencia como si eres un científico de datos que analiza las tendencias en el sector hotelero, el web scraping es una potente herramienta que puede ayudarte a recopilar los datos que necesitas de las páginas de Booking.

Al final de este tutorial, tendrás una comprensión sólida de cómo extraer datos de Booking.com utilizando la popular biblioteca de automatización de Node.js, Puppeteer. Nos centraremos en extraer detalles de anuncios de Madeira, Portugal, pero las técnicas y conceptos tratados en este tutorial también se pueden aplicar a otros sitios web y puntos de datos.

Requisitos previos

Si aún no tienes configurado tu entorno Node.js, solo tienes que dirigirte a su sitio web oficial para descargar la última versión para tu sistema operativo. A continuación, crea un nuevo directorio y ejecuta el siguiente comando para inicializar tu proyecto:

npm init -y

Usaremos TypeScript para escribir el código. Este superconjunto de JavaScript añade tipado estático opcional y otras características. Es útil para proyectos más grandes y puede facilitar la detección temprana de errores. Debes añadirlo a las dependencias de desarrollo del proyecto e inicializar su archivo de configuración:

npm install typescript -save-dev npx tsc -init

Solo asegúrate de que, en el archivo tsconfig.json recién generado, la propiedad «outDir» esté establecida en «dist», ya que queremos separar el código TypeScript del compilado.

Por último, el siguiente comando añadirá Puppeteer a las dependencias de nuestro proyecto:

npm install puppeteer

Puppeteer es una biblioteca de Node.js que proporciona una API de alto nivel para controlar un navegador Chrome sin interfaz gráfica, que se puede utilizar para tareas de web scraping y automatización

Ubicación de los datos

Para este tutorial, hemos elegido extraer los datos de las propiedades disponibles en las Islas de Madeira, Portugal: https://www.booking.com/searchresults.en-us.html?ss=Madeira+Islands&checkin=2023-01-13&checkout=2023-01-15. Es importante añadir las fechas de entrada y salida a la URL para que toda la información de las propiedades esté disponible.

Esta guía abarca la extracción de los siguientes datos de las propiedades:

  • el nombre
  • la URL
  • la dirección física
  • el precio
  • la valoración y el número de reseñas
  • la miniatura

Puedes verlos resaltados en la captura de pantalla siguiente:

Al abrir las Herramientas de desarrollador en cada uno de estos elementos, podrás ver los selectores CSS que utilizaremos para localizar los elementos HTML. Si eres bastante nuevo en el funcionamiento de los selectores CSS, no dudes en consultar esta guía para principiantes.

Análisis de los datos

Dado que todos los anuncios tienen la misma estructura y datos, podemos extraer toda la información de la lista completa de propiedades en nuestro algoritmo. Tras ejecutar el script, podemos recorrer todos los resultados y compilarlos en una única lista.

Tras un primer vistazo al documento HTML, es posible que hayas notado que la página web de Booking es bastante compleja y que los nombres de las clases se generan en su mayoría de forma aleatoria.

Por suerte para nosotros, el sitio web no se basa únicamente en los nombres de clase, y podemos utilizar el valor de un atributo específico como criterio de extracción. En la captura de pantalla anterior, hemos resaltado lo accesibles que son la miniatura, el nombre y la URL de una propiedad.

import puppeteer from 'puppeteer';

async function scrapeBookingData(booking_url: string): Promise<void> {

    // Launch Puppeteer

    const browser = await puppeteer.launch({

        headless: false,

    	  args: ['--start-maximized'],

    	  defaultViewport: null

    })

    const page = await browser.newPage()

    // Navigate to the channel URL

    await page.goto(booking_url)

    // Extract listings name

    const listings_name = await page.evaluate(() => {

        const names = document.querySelectorAll('div[data-testid="title"]')

    	  const names_array = Array.from(names)

    	  return names ? names_array.map(n => n.textContent) : []

    })

    console.log(listings_name)

    // Extract listings location

    const listings_location = await page.evaluate(() => {

        const locations = document.querySelectorAll('a[data-testid="title-link"]')

    	  const locations_array = Array.from(locations)

    	  return locations ? locations_array.map(l => l.getAttribute('href')) : []

    })

    console.log(listings_location)

    // Extract listings thumbnail

    const listings_thumbnail = await page.evaluate(() => {

        const thumbnails = document.querySelectorAll('[data-testid="image"]')

    	  const thumbnails_array = Array.from(thumbnails)

    	  return thumbnails ? thumbnails_array.map(t => t.getAttribute('src')) : []

    })

    console.log(listings_thumbnail)

    await browser.close()

}

scrapeBookingData("https://www.booking.com/searchresults.en-us.html?ss=Madeira+Islands&checkin=2023-01-13&checkout=2023-01-15")

Hemos utilizado Puppeteer para abrir una instancia del navegador, crear una nueva página, navegar hasta nuestra URL de destino, extraer los datos mencionados y, a continuación, cerrar el navegador. Para facilitar la depuración visual, estoy utilizando el modo no headless del navegador.

Como se ha explicado anteriormente, se pudo acceder fácilmente a los datos gracias al atributo «data-testid», que asignaba un valor único al elemento HTML. Ejecuta el siguiente comando para ejecutar el script:

npx tsc && node dist/index.js

Tu terminal debería mostrar 3 resultados en forma de lista del mismo tamaño, que representan los nombres, las URL y las miniaturas de todas las propiedades de la página actual.

Para la siguiente sección del documento HTML, hemos resaltado la dirección, la valoración y el número de reseñas de una propiedad.

// Extract listings address

const listings_address = await page.evaluate(() => {

    const addresses = document.querySelectorAll('[data-testid="address"]')

    const addresses_array = Array.from(addresses)

    return addresses ? addresses_array.map(a => a.textContent) : []

})

console.log(listings_address)

// Extract listings rating and review count

const listings_rating = await page.evaluate(() => {

    const ratings = document.querySelectorAll('[data-testid="review-score"]')

    const ratings_array = Array.from(ratings)

    return ratings ? ratings_array.map(r => r.textContent) : []

})

console.log(listings_rating)

Al igual que antes, hemos utilizado el atributo «data-testid». Al volver a ejecutar el script, deberían aparecer dos listas más, igual que las anteriores.

Y, por último, en la última sección, hemos extraído el precio de la propiedad. El código no será diferente de lo que hicimos antes:

// Extract listings price

const listings_price = await page.evaluate(() => {

    const prices = document.querySelectorAll('[data-testid="price-and-discounted-price"]')

    const prices_array = Array.from(prices)

    return prices ? prices_array.map(p => p.textContent) : []

})

console.log(listings_price)

Para facilitar el procesamiento posterior de los datos extraídos, combinaremos las listas resultantes en una sola.

// Group the lists

const listings = []

for (let i = 0; i < listings_name.length; i++) {

    listings.push({

        name: listings_name[i],

        url: listings_location[i],

        address: listings_address[i],

        price: listings_price[i],

        ratings: listings_rating[i],

        thumbnails: listings_thumbnail[i]

    })

}

console.log(listings)

El resultado final debería tener ahora este aspecto:

[

  {

    name: 'Pestana Churchill Bay',

    url: 'https://www.booking.com/hotel/pt/pestana-churchill-bay.html?aid=304142&label=gen173nr-1FCAQoggJCFnNlYXJjaF9tYWRlaXJhIGlzbGFuZHNIMVgEaMABiAEBmAExuAEXyAEM2AEB6AEB-AEDiAIBqAIDuAK9luydBsACAdICJGViMWY2MmRjLWJhZmEtNGZhZC04MDAyLWQ4MmU3YjU5MTMwZtgCBeACAQ&ucfs=1&arphpl=1&checkin=2023-01-13&checkout=2023-01-15&group_adults=2&req_adults=2&no_rooms=1&group_children=0&req_children=0&hpos=1&hapos=1&sr_order=popularity&srpvid=42cc81de452009eb&srepoch=1673202494&all_sr_blocks=477957801_262227867_0_1_0&highlighted_blocks=477957801_262227867_0_1_0&matching_block_id=477957801_262227867_0_1_0&sr_pri_blocks=477957801_262227867_0_1_0__18480&tpi_r=2&from_sustainable_property_sr=1&from=searchresults#hotelTmpl',

    address: 'Câmara de Lobos',

    price: '911 lei',

    ratings: '9.0Wonderful 727 reviews',

    thumbnails: 'https://cf.bstatic.com/xdata/images/hotel/square200/202313893.webp?k=824dc3908c4bd3e80790ce011f763f10fd4064dcb5708607f020f2e7c92d130e&o=&s=1'

  },

  {

    name: 'Hotel Madeira',

    url: 'https://www.booking.com/hotel/pt/madeira-funchal.html?aid=304142&label=gen173nr-1FCAQoggJCFnNlYXJjaF9tYWRlaXJhIGlzbGFuZHNIMVgEaMABiAEBmAExuAEXyAEM2AEB6AEB-AEDiAIBqAIDuAK9luydBsACAdICJGViMWY2MmRjLWJhZmEtNGZhZC04MDAyLWQ4MmU3YjU5MTMwZtgCBeACAQ&ucfs=1&arphpl=1&checkin=2023-01-13&checkout=2023-01-15&group_adults=2&req_adults=2&no_rooms=1&group_children=0&req_children=0&hpos=2&hapos=2&sr_order=popularity&srpvid=42cc81de452009eb&srepoch=1673202494&all_sr_blocks=57095605_262941681_2_1_0&highlighted_blocks=57095605_262941681_2_1_0&matching_block_id=57095605_262941681_2_1_0&sr_pri_blocks=57095605_262941681_2_1_0__21200&tpi_r=2&from_sustainable_property_sr=1&from=searchresults#hotelTmpl',

    address: 'Se, Funchal',

    price: '1,045 lei',

    ratings: '8.3Very Good 647 reviews',

    thumbnails: 'https://cf.bstatic.com/xdata/images/hotel/square200/364430623.webp?k=8c1e510da2aad0fc9ff5731c3874e05b1c4cceec01a07ef7e9db944799771724&o=&s=1'

  },

  {

    name: 'Les Suites at The Cliff Bay - PortoBay',

    url: 'https://www.booking.com/hotel/pt/les-suites-at-the-cliff-bay.html?aid=304142&label=gen173nr-1FCAQoggJCFnNlYXJjaF9tYWRlaXJhIGlzbGFuZHNIMVgEaMABiAEBmAExuAEXyAEM2AEB6AEB-AEDiAIBqAIDuAK9luydBsACAdICJGViMWY2MmRjLWJhZmEtNGZhZC04MDAyLWQ4MmU3YjU5MTMwZtgCBeACAQ&ucfs=1&arphpl=1&checkin=2023-01-13&checkout=2023-01-15&group_adults=2&req_adults=2&no_rooms=1&group_children=0&req_children=0&hpos=3&hapos=3&sr_order=popularity&srpvid=42cc81de452009eb&srepoch=1673202494&all_sr_blocks=395012401_247460894_2_1_0&highlighted_blocks=395012401_247460894_2_1_0&matching_block_id=395012401_247460894_2_1_0&sr_pri_blocks=395012401_247460894_2_1_0__100000&tpi_r=2&from_sustainable_property_sr=1&from=searchresults#hotelTmpl',

    address: 'Sao Martinho, Funchal',

    price: '4,928 lei',

    ratings: '9.5Exceptional 119 reviews',

    thumbnails: 'https://cf.bstatic.com/xdata/images/hotel/square200/270120962.webp?k=68ded1031f5082597c48eb25c833ea7fcedc2ec2bc5d555adfcac98b232f9745&o=&s=1'

  }

]

Alternativas

Aunque el tutorial hasta este punto ha parecido sencillo, debemos mencionar las dificultades que suelen surgir en el web scraping, especialmente en el caso de que quieras ampliar tu proyecto.

Hoy en día, los sitios web implementan diversas técnicas de detección de bots y recopilan datos del navegador para poder prevenir o bloquear el tráfico automatizado. Booking.com no es una excepción a esta regla. Mediante la protección de PerimeterX, el sitio web realiza comprobaciones de tu IP y recopila múltiples datos:

  • propiedades del objeto Navigator (deviceMemory, languages, platform, userAgent, webdriver, etc.)
  • enumeración de fuentes y complementos
  • comprobaciones de las dimensiones de la pantalla
  • y mucho más.

Una solución a estos retos es utilizar una API de scraping, que ofrece una forma sencilla y fiable de acceder a los datos de sitios web como Booking.com sin necesidad de crear y mantener tu propio scraper.

WebScrapingAPI es un producto de este tipo, que utiliza la rotación de proxies para eludir los CAPTCHAs y aleatoriza los datos del navegador para imitar a un usuario real. Para empezar, solo tienes que registrarte y obtener tu clave API desde el panel de control. Esta clave se utiliza para autenticar tus solicitudes.

Para probar rápidamente la API con el proyecto Node.js ya existente, podemos utilizar su SDK correspondiente. Solo tienes que ejecutar el siguiente comando:

npm install webscrapingapi

Ahora, todo lo que tienes que hacer es ajustar los selectores CSS anteriores a la API. La función de reglas de extracción te permite analizar datos con modificaciones mínimas, lo que la convierte en una herramienta poderosa en tu kit de herramientas de web scraping.

import webScrapingApiClient from 'webscrapingapi';

const client = new webScrapingApiClient("YOUR_API_KEY");

async function exampleUsage() {

    const api_params = {

        'render_js': 1,

    	  'proxy_type': 'datacenter',

    	  'timeout': 60000,

    	  'extract_rules': JSON.stringify({

            names: {

                selector: 'div[data-testid="title"]',

                output: 'text',

                all: '1'

        	},

        	locations: {

                selector: 'a[data-testid="title-link"]',

                output: '@href',

                all: '1'

        	},

        	addresses: {

                selector: '[data-testid="address"]',

                output: 'text',

                all: '1'

        	},

        	prices: {

                selector: '[data-testid="price-and-discounted-price"]',

                output: 'text',

                all: '1'

        	},

        	ratings: {

                selector: '[data-testid="review-score"]',

                output: 'text',

                all: '1'

        	},

        	thumbnails: {

                selector: '[data-testid="image"]',

                output: '@src',

                all: '1'

        	}

        })

    }

    const URL = "https://www.booking.com/searchresults.en-us.html?ss=Madeira+Islands&checkin=2023-01-13&checkout=2023-01-15"

    const response = await client.get(URL, api_params)

    if (response.success) {

        // Group the lists

    	  const listings = []

    	  for (let i = 0; i < response.response.data.names.length; i++) {

            listings.push({

               name: response.response.data.names[i],

               url: response.response.data.locations[i],

               address: response.response.data.addresses[i],

               price: response.response.data.prices[i],

               ratings: response.response.data.ratings[i],

               thumbnails: response.response.data.thumbnails[i]

            })

        }

        console.log(listings)

    } else {

        console.log(response.error.response.data)

    }

}

exampleUsage();

Conclusión

En este tutorial, hemos cubierto los conceptos básicos de cómo extraer datos de Booking.com utilizando Node.js y Puppeteer. Te hemos mostrado cómo configurar tu entorno y extraer los detalles de los anuncios de Madeira, Portugal. Sin embargo, estas técnicas y conceptos también se pueden aplicar a otros sitios web y puntos de datos.

El web scraping puede ser una herramienta increíblemente útil tanto para empresas como para científicos de datos. Al recopilar datos de Booking.com, puedes obtener información valiosa sobre el sector hotelero, evaluar a la competencia y mucho más. Sin embargo, es importante tener en cuenta que el web scraping puede infringir las condiciones de uso de algunos sitios web, por lo que siempre es recomendable consultar las políticas específicas antes de continuar.

Aunque es posible crear su propio rastreador web, recurrir a un servicio profesional suele ser una opción más segura y eficiente, especialmente para proyectos de mayor envergadura. Un rastreador profesional contará con la experiencia y los recursos necesarios para hacer frente a cualquier reto que pueda surgir y ofrecer resultados de alta calidad.

Esperamos que hayas disfrutado de este tutorial y que ahora te sientas preparado para recopilar datos valiosos de Booking.com utilizando un entorno Node.js. ¡Gracias por leer!

Acerca del autor
Raluca Penciuc, Desarrollador full-stack @ WebScrapingAPI
Raluca PenciucDesarrollador full-stack

Raluca Penciuc es desarrolladora full stack en WebScrapingAPI, donde se dedica a crear rastreadores, mejorar las técnicas de evasión y buscar formas fiables de reducir la detección en los sitios web de destino.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.