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

Cómo extraer datos de Idealista: una guía completa (Actualización de 2023)

Cómo extraer datos de Idealista: una guía completa (Actualización de 2023)

Idealista es uno de los principales portales inmobiliarios del sur de Europa, que ofrece una gran cantidad de información sobre propiedades en venta y alquiler. Está disponible en España, Portugal e Italia, y cuenta con millones de viviendas, habitaciones y apartamentos en su catálogo.

Para empresas y particulares que deseen conocer mejor el mercado inmobiliario español, el sitio web puede ser una herramienta muy valiosa. El web scraping de Idealista puede ayudarte a extraer esta valiosa información y utilizarla de diversas formas, como para realizar estudios de mercado, generar clientes potenciales y crear nuevas oportunidades de negocio.

En este artículo, te ofrecemos una guía paso a paso sobre cómo extraer datos de la web utilizando TypeScript. Abordaremos los requisitos previos, la extracción propiamente dicha de los datos de las propiedades y cómo mejorar el proceso, así como por qué es mejor utilizar un extractor profesional que crear uno propio.

Al final del artículo, tendrás los conocimientos y las herramientas necesarios para extraer datos de Idealista y aprovecharlos al máximo para tu negocio.

Requisitos previos

Antes de empezar, asegurémonos de que contamos con las herramientas necesarias.

En primer lugar, descarga e instala Node.js desde la página web oficial, asegurándote de utilizar la versión de soporte a largo plazo (LTS). Esto también instalará automáticamente Node Package Manager (NPM), que utilizaremos para instalar otras dependencias.

Para este tutorial, utilizaremos Visual Studio Code como nuestro entorno de desarrollo integrado (IDE), pero puedes usar cualquier otro IDE de tu elección. Crea una nueva carpeta para tu proyecto, abre el terminal y ejecuta el siguiente comando para configurar un nuevo proyecto de Node.js:

npm init -y

Esto creará un archivo package.json en el directorio de tu proyecto, que almacenará información sobre tu proyecto y sus dependencias.

A continuación, debemos instalar TypeScript y las definiciones de tipos para Node.js. TypeScript ofrece tipado estático opcional, lo que ayuda a prevenir errores en el código. Para ello, ejecuta en la terminal:

npm install typescript @types/node --save-dev

Puedes verificar la instalación ejecutando:

npx tsc --version

TypeScript utiliza un archivo de configuración llamado tsconfig.json para almacenar las opciones del compilador y otros ajustes. Para crear este archivo en tu proyecto, ejecuta el siguiente comando:

npx tsc -init

Asegúrate de que el valor de «outDir» esté establecido en «dist». De esta forma separaremos los archivos de TypeScript de los compilados. Puedes encontrar más información sobre este archivo y sus propiedades en la documentación oficial de TypeScript.

Ahora, crea un directorio «src» en tu proyecto y un nuevo archivo «index.ts». Aquí es donde guardaremos el código de scraping. Para ejecutar código TypeScript hay que compilarlo primero, así que, para asegurarnos de no olvidarnos de este paso adicional, podemos usar un comando definido por nosotros mismos.

Ve al archivo «package.json» y edita la sección «scripts» de la siguiente manera:

"scripts": {

    "test": "npx tsc && node dist/index.js"

}

De esta forma, cuando ejecutes el script, solo tendrás que escribir «npm run test» en tu terminal.

Por último, para extraer los datos del sitio web, utilizaremos Puppeteer, una biblioteca de navegador sin interfaz gráfica para Node.js que te permite controlar un navegador web e interactuar con sitios web mediante programación. Para instalarlo, ejecuta este comando en la terminal:

npm install puppeteer

Es muy recomendable si quieres asegurarte de que tus datos estén completos, ya que muchos sitios web actuales contienen contenido generado dinámicamente. Si tienes curiosidad, puedes echar un vistazo a la documentación de Puppeteer antes de continuar para ver todo lo que es capaz de hacer.

Localización de los datos

Ahora que ya tienes tu entorno configurado, podemos empezar a ver cómo extraer los datos. Para este artículo, he elegido extraer la lista de casas y apartamentos disponibles en una región de Toledo, España: https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/.

Vamos a extraer los siguientes datos de cada anuncio de la página:

  • la URL;
  • el título;
  • el precio;
  • los detalles (número de habitaciones, superficie, etc.);
  • la descripción

Puedes ver toda esta información resaltada en la captura de pantalla que aparece a continuación:

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.

Extracción de datos

Para empezar a escribir nuestro script, comprobemos que la instalación de Puppeteer se ha realizado correctamente:

import puppeteer from 'puppeteer';

async function scrapeIdealistaData(idealista_url: string): Promise<void> {

    

    // Launch Puppeteer

    const browser = await puppeteer.launch({

        headless: false,

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

    	  defaultViewport: null

    })

    // Create a new page

    const page = await browser.newPage()

    // Navigate to the target URL

    await page.goto(idealista_url)

    // Close the browser

    await browser.close()

}

scrapeIdealistaData("https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/")

Aquí abrimos una ventana del navegador, creamos una nueva página, navegamos a nuestra URL de destino y cerramos el navegador. En aras de la simplicidad y la depuración visual, abro la ventana del navegador maximizada en modo no headless.

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.

Para obtener la URL de todas las propiedades, localizamos los elementos de anclaje con la clase «item-link». A continuación, convertimos el resultado en una matriz de JavaScript y asignamos cada elemento al valor del atributo «href».

// Extract listings location

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

    const locations = document.querySelectorAll('a.item-link')

    const locations_array = Array.from(locations)

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

})

console.log(listings_location.length, listings_location)

A continuación, para los títulos, podemos utilizar el mismo elemento de anclaje, salvo que esta vez extraeremos su atributo «title».

// Extract listings titles

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

    const titles = document.querySelectorAll('a.item-link')

    const titles_array = Array.from(titles)

    return titles ? titles_array.map(t => t.getAttribute('title')) : []

})

console.log(listings_title.length, listings_title)

En cuanto a los precios, localizamos los elementos «span» que tienen dos nombres de clase: «item-price» y «h2-simulated». Es importante identificar los elementos de la forma más única posible, para no alterar el resultado final. También hay que convertirlos en una matriz y luego asignarlos a su contenido de texto.

// Extract listings prices

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

    const prices = document.querySelectorAll('span.item-price.h2-simulated')

    const prices_array = Array.from(prices)

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

})

console.log(listings_price.length, listings_price)

Aplicamos el mismo principio a los detalles de la propiedad, analizando los elementos «div» con el nombre de clase «item-detail-char».

// Extract listings details

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

    const details = document.querySelectorAll('div.item-detail-char')

    const details_array = Array.from(details)

    return details ? details_array.map(d => d.textContent) : []

})

console.log(listings_detail.length, listings_detail)

Y, por último, la descripción de las propiedades. Aquí aplicamos una expresión regular adicional para eliminar todos los caracteres de salto de línea innecesarios.

// Extract listings descriptions

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

    const descriptions = document.querySelectorAll('div.item-description.description')

    const descriptions_array = Array.from(descriptions)

    return descriptions ? descriptions_array.map(d => d.textContent.replace(/(\r\n|\n|\r)/gm, "")) : []

})

console.log(listings_description.length, listings_description)

Ahora deberías tener 5 listas, una para cada dato que hemos extraído. Como mencioné antes, debemos centralizarlas en una sola. De esta manera, la información que hemos recopilado será mucho más fácil de procesar posteriormente.

// Group the lists

const listings = []

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

    listings.push({

        url: listings_location[i],

        title: listings_title[i],

        price: listings_price[i],

        details: listings_detail[i],

        description: listings_description[i]

    })

}

console.log(listings.length, listings)

El resultado final debería tener este aspecto:

[

  {

    url: '/pt/inmueble/99004556/',

    title: 'Apartamento em ronda de Buenavista, Buenavista-Valparaíso-La Legua, Toledo',

    price: '750€/mês',

    details: '\n3 quart.\n115 m² área bruta\n2º andar exterior com elevador\nOntem \n',

    description: 'Apartamento para alugar na Ronda Buenavista, em Toledo.Três quartos e duas casas de banho, sala, cozinha, terraço, garagem e arrecadação....'

  },

  {

    url: '/pt/inmueble/100106615/',

    title: 'Moradia em banda em Buenavista-Valparaíso-La Legua, Toledo',

    price: '1.000€/mês',

    details: '\n4 quart.\n195 m² área bruta\nOntem \n',

    description: 'Magnífica casa geminada para alugar com 3 andares, 4 quartos aconchegantes, 3 banheiros, sala ampla e luminosa, cozinha totalmente equipa...'

  },

  {

    url: '/pt/inmueble/100099977/',

    title: 'Moradia em banda em calle Francisco Ortiz, Buenavista-Valparaíso-La Legua, Toledo',

    price: '800€/mês',

    details: '\n3 quart.\n118 m² área bruta\n10 jan \n',

    description: 'O REMAX GRUPO FV aluga uma casa mobiliada na Calle Francisco Ortiz, em Toledo.Moradia geminada com 148 metros construídos, distribuídos...'

  },

  {

    url: '/pt/inmueble/100094142/',

    title: 'Apartamento em Buenavista-Valparaíso-La Legua, Toledo',

    price: '850€/mês',

    details: '\n4 quart.\n110 m² área bruta\n1º andar exterior com elevador\n10 jan \n',

    description: 'Apartamento muito espaçoso para alugar sem móveis, cozinha totalmente equipada.Composto por 4 quartos, 1 casa de banho, terraço.Calefaç...'

  }

]

Evitar la detección de bots

Si ejecutas tu script al menos dos veces durante este tutorial, es posible que ya te hayas topado con esta molesta página:

Idealista utiliza DataDome como protección antibots, que incorpora un desafío CAPTCHA de GeeTest. Debes mover las piezas del rompecabezas hasta completar la imagen, y entonces deberías ser redirigido de nuevo a tu página de destino.

Puedes pausar fácilmente tu script de Puppeteer hasta que resuelvas el desafío utilizando este código:

await page.waitForFunction(() => {

    const pageContent = document.getElementById('main-content')

    return pageContent !== null

}, {timeout: 10000})

Esto le indica a nuestro script que espere 10 segundos a que aparezca un selector CSS específico en el DOM. Debería ser suficiente para que resuelvas el CAPTCHA y luego dejes que se complete la navegación.

… A menos que la página de Idealista te bloquee de todos modos.

En este punto, el proceso se volvió más complejo y desafiante, y ni siquiera has ampliado tu proyecto.

Como mencioné antes, Idealista está protegida por DataDome. Recopilan múltiples datos del navegador para generar y asociarte con una huella digital única. Si sospechan de ti, recibes el desafío CAPTCHA anterior, que es bastante difícil de resolver automáticamente.

Entre los datos del navegador recopilados encontramos:

  • propiedades del objeto Navigator (deviceMemory, hardwareConcurrency, languages, platform, userAgent, webdriver, etc.)
  • comprobaciones de tiempo y rendimiento
  • WebGL
  • WebRTC rastreo de IP
  • registro de movimientos del ratón
  • inconsistencias entre el User-Agent y tu sistema operativo
  • y muchas más.

Una forma de superar estos retos y seguir realizando scraping a gran escala es utilizar una API de scraping. Este tipo de servicios ofrecen una forma sencilla y fiable de acceder a datos de sitios web como Idealista.com, sin necesidad de crear y mantener tu propio scraper.

WebScrapingAPI es un ejemplo de este tipo de productos. Su mecanismo de rotación de proxies evita por completo los CAPTCHAs, y su amplia base de conocimientos permite aleatorizar los datos del navegador para que parezca un usuario real.

La configuración es rápida y sencilla. Solo tienes que registrarte para recibir tu clave API. Se puede acceder a ella desde tu panel de control y se utiliza para autenticar las solicitudes que envías.

Como ya ha configurado su entorno Node.js, podemos utilizar el SDK correspondiente. Ejecute el siguiente comando para añadirlo a las dependencias de su proyecto:

npm install webscrapingapi

Ahora solo queda ajustar los selectores CSS anteriores a la API. La potente función de reglas de extracción permite analizar los datos sin modificaciones significativas.

import webScrapingApiClient from 'webscrapingapi';

const client = new webScrapingApiClient("YOUR_API_KEY");

async function exampleUsage() {

    const api_params = {

        'render_js': 1,

    	  'proxy_type': 'residential',

    	  'timeout': 60000,

    	  'extract_rules': JSON.stringify({

            locations: {

                selector: 'a.item-link',

                output: '@href',

                all: '1'

        	},

        	titles: {

                selector: 'a.item-link',

                output: '@title',

                all: '1'

        	},

        	prices: {

                selector: 'span.item-price.h2-simulated',

                output: 'text',

                all: '1'

        	},

        	details: {

                selector: 'div.item-detail-char',

                output: 'text',

                all: '1'

        	},

        	descriptions: {

                selector: 'div.item-description.description',

                output: 'text',

                all: '1'

        	}

        })

    }

    const URL = "https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/"

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

    if (response.success) {

        // Group the lists

    	  const listings = []

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

            listings.push({

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

                title: response.response.data.titles[i],

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

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

                description: response.response.data.descriptions[i].replace(/(\r\n|\n|\r)/gm, "")

        	})

    	  }

    	  console.log(listings.length, listings)

    } else {

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

    }

}

exampleUsage();

Conclusión

En este artículo, te hemos mostrado cómo extraer datos de Idealista, una popular web inmobiliaria española, utilizando TypeScript y Puppeteer. Hemos repasado el proceso de configuración de los requisitos previos y la extracción de datos, y hemos comentado algunas formas de mejorar el código.

El scraping de Idealista puede proporcionar información valiosa tanto para empresas como para particulares. Utilizando las técnicas descritas en este artículo, puedes extraer datos como las URL de las propiedades, los precios y las descripciones de la web.

Además, si quieres evitar las medidas antibot y la complejidad del proceso de scraping, utilizar un scraper profesional puede resultar más eficiente y fiable que crear uno propio.

Siguiendo los pasos y las técnicas descritas en esta guía, podrás aprovechar todo el potencial del scraping web de Idealista y utilizarlo para satisfacer las necesidades de tu negocio. Ya sea para estudios de mercado, generación de clientes potenciales o la creación de nuevas oportunidades de negocio, el scraping web de Idealista puede ayudarte a mantenerte por delante de la competencia.

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.