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

Web scraping para el sector inmobiliario: cómo extraer datos de Realtor.com como un profesional

Web scraping para el sector inmobiliario: cómo extraer datos de Realtor.com como un profesional

Recopilar datos precisos y actualizados es fundamental para empresas y particulares de muchos sectores, y el inmobiliario no es una excepción. Realtor.com es un sitio web muy popular para buscar pisos y casas en venta o alquiler, ya que contiene una gran cantidad de información que puede resultar muy valiosa para profesionales del sector inmobiliario, inversores y compradores de vivienda.

En este tutorial, te mostraré cómo extraer datos de Realtor.com para que dispongas de la información necesaria para poner en marcha tu proyecto. Te guiaré a través del proceso de configuración de un proyecto, navegación a Realtor.com y extracción de los datos deseados.

También comentaré formas de mejorar la fiabilidad y la eficiencia del rastreador, y por qué utilizar un servicio profesional de rastreo puede ser una mejor opción para algunos casos de uso.

Al final de este tutorial, deberías tener una buena comprensión de cómo extraer datos de realtor.com, independientemente de tu profesión: ya seas un profesional del sector inmobiliario en busca de una ventaja competitiva, un inversor que busca nuevas oportunidades o un comprador de vivienda que busca la propiedad perfecta.

Configuración del entorno

Antes de empezar a extraer datos, debes instalar Node.js en tu ordenador. Puedes descargar la última versión desde la página web oficial y seguir las instrucciones correspondientes a tu sistema operativo.

A continuación, crea un nuevo directorio para tu proyecto y accede a él desde tu terminal o línea de comandos. Ejecuta el siguiente comando para inicializar 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.

Para instalar TypeScript, ejecuta el siguiente comando:

npm install typescript -save-dev

TypeScript es un superconjunto de JavaScript que añade tipado estático opcional y otras características. Es útil para proyectos de mayor envergadura y puede facilitar la detección temprana de errores. 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.

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.

Y por último, pero no menos importante, ejecuta el siguiente comando para añadir Puppeteer a las dependencias de tu 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. Es muy recomendable cuando se quiere garantizar la integridad de los datos, ya que muchos sitios web actuales contienen contenido generado dinámicamente.

Selección de 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 apartamentos tipo estudio disponibles para alquilar en Plano, Texas: https://www.realtor.com/apartments/Plano_TX/beds-studio.

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

  • la URL;
  • los precios;
  • el número de baños;
  • las superficies (medidas en pies cuadrados);
  • las direcciones físicas

Puedes ver toda esta información resaltada en la captura de pantalla siguiente:

Extracción de datos

Para extraer todos estos datos, primero tendremos que localizarlos. Haz clic con el botón derecho del ratón en las secciones resaltadas y, a continuación, selecciona «Inspeccionar» para abrir las Herramientas de desarrollador y ver el documento HTML. Al pasar el cursor del ratón por encima, podrás ver fácilmente qué parte corresponde a cada sección:

Para este tutorial, utilizaré selectores CSS, ya que son la opción más sencilla. Si eres nuevo en este método, no dudes en consultar primero esta guía autoexplicativa.

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

import puppeteer from 'puppeteer';

async function scrapeRealtorData(realtor_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(realtor_url)

    // Close the browser

    await browser.close()

}

scrapeRealtorData("https://www.realtor.com/apartments/Plano_TX/beds-studio")

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

Dado que cada anuncio tiene la misma estructura y los mismos datos, en nuestro algoritmo extraeremos toda la información de la lista completa de propiedades. Al final del script, recorreremos todos los resultados y los centralizaremos en una única lista.

Quizá hayas notado que la URL del anuncio no era visible en la primera captura de pantalla, pero se mencionaba y resaltaba en la segunda. Esto se debe a que, al hacer clic en él, se te redirige a la URL de la propiedad.

// Extract listings location

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

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

    const locations_array = Array.from(locations)

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

})

console.log(listings_location)

Localizamos la URL seleccionando los elementos de anclaje que tienen el atributo «data-testid» con el valor «card-link». A continuación, convertimos el resultado en una matriz de JavaScript y asignamos cada elemento al valor del atributo «href».

Sin embargo, la lista resultante contendrá cada URL dos veces. Esto se debe a que cada anuncio tiene el mismo elemento de anclaje para dos secciones: las imágenes de la propiedad y los detalles del alquiler. Podemos solucionar esto fácilmente utilizando la estructura de datos Set:

const unique_listings_location = [...new Set(listings_location)]

console.log(unique_listings_location)

Para el precio de la propiedad, extraeremos los elementos «div» que tengan el atributo «data-testid» con el valor «card-price». También hay que convertirlo en una matriz y luego asignarlo a su contenido de texto.

// Extract listings price

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

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

    const prices_array = Array.from(prices)

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

})

console.log(listings_price)

Para obtener el número de baños y la superficie de la propiedad, utilizaremos el operador para elementos hijos directos. Esto significa que el elemento padre se identifica de forma única, mientras que el elemento hijo tiene un identificador o nombre de clase más genérico. Aparte de eso, la lógica es la misma que antes:

// Extract listings baths

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

    const baths = document.querySelectorAll('li[data-testid="property-meta-baths"] > span[data-testid="meta-value"]')

    const baths_array = Array.from(baths)

    return baths ? baths_array.map(b => b.textContent) : []

})

console.log(listings_baths)

// Extract listings sqft

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

    const sqfts = document.querySelectorAll('li[data-testid="property-meta-sqft"] > span[data-testid="screen-reader-value"]')

    const sqfts_array = Array.from(sqfts)

    return sqfts ? sqfts_array.map(s => s.textContent) : []

})

console.log(listings_sqft)

Y, por último, para las direcciones de los anuncios, seleccionamos los elementos «div» que tienen el atributo «data-testid» establecido con el valor «card-address».

// Extract listings address

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

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

    const addresses_array = Array.from(addresses)

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

})

console.log(listings_address)

Ahora deberías tener 5 listas, una para cada dato que hemos extraído. Como mencioné antes, deberíamos centralizarlas en una sola. De esta forma, 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 < unique_listings_location.length; i++) {

    listings.push({

        url: unique_listings_location[i],

        price: listings_price[i],

        baths: listings_baths[i],

        sqft: listings_sqft[i],

        address: listings_address[i]

    })

}

console.log(listings)

El resultado final debería tener un aspecto similar a este:

[

    {

        url: '/realestateandhomes-detail/1009-14th-St-Apt-410_Plano_TX_75074_M92713-98757',  

        price: '$1,349',

        baths: '1',

	  sqft: '602 square feet',

	  address: '1009 14th St Apt 410Plano, TX 75074'

    },

    {

	  url: '/realestateandhomes-detail/1009-14th-St-Apt-1_Plano_TX_75074_M95483-11211',    

	  price: '$1,616',

	  baths: '1',

	  sqft: '604 square feet',

	  address: '1009 14th St Apt 1Plano, TX 75074'

    },

    {

	  url: '/realestateandhomes-detail/1009-14th-St_Plano_TX_75074_M87662-45547',

	  price: '$1,605 - $2,565',

	  baths: '1 - 2',

	  sqft: '602 - 1,297 square feet',

	  address: '1009 14th StPlano, TX 75074'

    },

    {

	  url: '/realestateandhomes-detail/5765-Bozeman-Dr_Plano_TX_75024_M70427-45476',  	 

	  price: '$1,262 - $2,345',

	  baths: '1 - 2',

	  sqft: '352 - 1,588 square feet',

	  address: '5765 Bozeman DrPlano, TX 75024'

    },

    {

	  url: '/realestateandhomes-detail/1410-K-Ave-Ste-1105A_Plano_TX_75074_M97140-46163',  

	  price: '$1,250 - $1,995',

	  baths: '1 - 2',

	  sqft: '497 - 1,324 square feet',

	  address: '1410 K Ave Ste 1105APlano, TX 75074'

    }

]

Evita la detección de bots

Aunque extraer datos de Realtor puede parecer fácil al principio, el proceso puede volverse más complejo y desafiante a medida que amplías tu proyecto. El sitio web inmobiliario implementa diversas técnicas para detectar y prevenir el tráfico automatizado, por lo que tu extractor ampliado empezará a ser bloqueado.

Realtor utiliza el modelo «Press & Hold» de CAPTCHA, ofrecido por PerimeterX, que es conocido por ser casi imposible de resolver desde tu código. Además de esto, el sitio web también recopila múltiples datos del navegador para generar y asociarte con una huella digital única.

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
  • y muchos 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 Realtor.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 obtener tu clave API. Puedes 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': 'datacenter',

    	  'timeout': 60000,

    	  'extract_rules': JSON.stringify({

            locations: {

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

                output: '@href',

                all: '1'

        	},

        	prices: {

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

                output: 'text',

                all: '1'

        	},

        	baths: {

                selector: 'li[data-testid="property-meta-baths"] > span[data-testid="meta-value"]',

                output: 'text',

                all: '1'

        	},

        	sqfts: {

                selector: 'li[data-testid="property-meta-sqft"] > span[data-testid="screen-reader-value"]',

                output: 'text',

                all: '1'

        	},

        	addresses: {

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

                output: 'text',

                all: '1'

        	}

        })

    }

    const URL = "https://www.realtor.com/apartments/Plano_TX/beds-studio"

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

    if (response.success) {

        const unique_listings_location = [...new Set(response.response.data.locations)]

    	  // Group the lists

    	  const listings = []

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

            listings.push({

                url: unique_listings_location[i],

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

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

                sqft: response.response.data.sqfts[i],

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

            })

    	  }

    	  console.log(listings)

    } else {

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

    }

}

exampleUsage();

Conclusión

En este tutorial, hemos proporcionado una guía paso a paso sobre cómo extraer datos de realtor.com utilizando Node.js y Puppeteer. También hemos analizado formas de mejorar la fiabilidad y la eficiencia del extractor, y por qué utilizar un servicio de extracción profesional puede ser una mejor opción para algunos casos de uso.

Realtor.com es una fuente popular y valiosa de datos inmobiliarios, y con las habilidades y conocimientos que has adquirido en este tutorial, ahora deberías ser capaz de utilizar el web scraping para extraer estos datos y aplicarlos a tus propios proyectos.

Tanto si eres un profesional del sector inmobiliario en busca de una ventaja competitiva, un inversor que busca nuevas oportunidades o un comprador de vivienda que busca la propiedad perfecta, el web scraping puede proporcionarte información y datos valiosos de realtor.com. Esperamos que este tutorial te haya resultado útil y que ahora estés listo para llevar tu actividad inmobiliaria al siguiente nivel con la ayuda del web scraping de realtor.com.

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.