Zurück zum Blog
Anleitungen
Raluca PenciucLast updated on Mar 31, 20267 min read

Web-Scraping für die Immobilienbranche: So extrahieren Sie Daten von Realtor.com wie ein Profi

Web-Scraping für die Immobilienbranche: So extrahieren Sie Daten von Realtor.com wie ein Profi

Das Sammeln genauer und aktueller Daten ist für Unternehmen und Privatpersonen in vielen Branchen von entscheidender Bedeutung, und die Immobilienbranche bildet da keine Ausnahme. Realtor.com ist eine beliebte Website für die Suche nach Wohnungen und Häusern zum Verkauf oder zur Miete, da sie eine Fülle von Informationen enthält, die für Immobilienfachleute, Investoren und Hauskäufer wertvoll sein können.

In diesem Tutorial zeige ich Ihnen, wie Sie Daten von Realtor.com scrapen können, damit Sie über die Daten verfügen, die Sie für den Start Ihres Projekts benötigen. Ich werde den Prozess der Projekteinrichtung, der Navigation zu Realtor.com und der Extraktion der gewünschten Daten Schritt für Schritt durchgehen.

Außerdem werde ich Möglichkeiten zur Verbesserung der Zuverlässigkeit und Effizienz des Scrapers erörtern und erläutern, warum die Nutzung eines professionellen Scraper-Dienstes für manche Anwendungsfälle die bessere Option sein kann.

Am Ende dieses Tutorials sollten Sie ein gutes Verständnis dafür haben, wie man realtor.com scrapt, unabhängig von Ihrem Beruf: ob Sie als Immobilienfachmann nach einem Wettbewerbsvorteil suchen, als Investor nach neuen Möglichkeiten oder als Hauskäufer nach der perfekten Immobilie.

Einrichtung der Umgebung

Bevor Sie mit dem Scraping beginnen können, müssen Sie Node.js auf Ihrem Computer installieren. Sie können die neueste Version von der offiziellen Website herunterladen und die Anweisungen entsprechend Ihrem Betriebssystem befolgen.

Erstellen Sie anschließend ein neues Verzeichnis für Ihr Projekt und wechseln Sie in Ihrem Terminal oder der Eingabeaufforderung dorthin. Führen Sie den folgenden Befehl aus, um ein neues Node.js-Projekt zu initialisieren:

npm init -y

Dadurch wird in Ihrem Projektverzeichnis eine Datei namens package.json erstellt, in der Informationen zu Ihrem Projekt und dessen Abhängigkeiten gespeichert werden.

Um TypeScript zu installieren, führen Sie den folgenden Befehl aus:

npm install typescript -save-dev

TypeScript ist eine Obermenge von JavaScript, die optionale statische Typisierung und weitere Funktionen hinzufügt. Es ist nützlich für größere Projekte und kann es einfacher machen, Fehler frühzeitig zu erkennen. TypeScript verwendet eine Konfigurationsdatei namens tsconfig.json, um Compiler-Optionen und andere Einstellungen zu speichern. Um diese Datei in Ihrem Projekt zu erstellen, führen Sie den folgenden Befehl aus:

npx tsc -init

Stellen Sie sicher, dass der Wert für „outDir“ auf „dist“ gesetzt ist. Auf diese Weise trennen wir die TypeScript-Dateien von den kompilierten Dateien.

Erstellen Sie nun ein Verzeichnis „src“ in Ihrem Projekt und eine neue Datei „index.ts“. Hier werden wir den Scraping-Code ablegen. Um TypeScript-Code auszuführen, müssen Sie ihn zunächst kompilieren. Damit wir diesen zusätzlichen Schritt nicht vergessen, können wir einen benutzerdefinierten Befehl verwenden.

Öffne die Datei „package.json“ und bearbeite den Abschnitt „scripts“ wie folgt:

"scripts": {

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

}

Auf diese Weise müssen Sie beim Ausführen des Skripts lediglich „npm run test“ in Ihr Terminal eingeben.

Und zu guter Letzt führen Sie den folgenden Befehl aus, um Puppeteer zu den Abhängigkeiten Ihres Projekts hinzuzufügen:

npm install puppeteer

Puppeteer ist eine Node.js-Bibliothek, die eine High-Level-API zur Steuerung eines headless Chrome-Browsers bereitstellt, der für Web-Scraping und Automatisierungsaufgaben genutzt werden kann. Sie ist sehr empfehlenswert, wenn du die Vollständigkeit deiner Daten sicherstellen möchtest, da viele Websites heutzutage dynamisch generierte Inhalte enthalten.

Datenauswahl

Nachdem Sie nun Ihre Umgebung eingerichtet haben, können wir uns mit der Datenextraktion befassen. Für diesen Artikel habe ich mich entschieden, die Liste der zur Miete verfügbaren Studio-Apartments in Plano, TX, zu scrapen: https://www.realtor.com/apartments/Plano_TX/beds-studio.

Wir werden die folgenden Daten aus jedem Eintrag auf der Seite extrahieren:

  • die URL;
  • die Preise;
  • die Anzahl der Badezimmer;
  • die Wohnfläche (in Quadratfuß);
  • die physischen Adressen

All diese Informationen sind im folgenden Screenshot hervorgehoben:

Datenextraktion

Um all diese Daten zu extrahieren, müssen wir sie zunächst lokalisieren. Klicken Sie mit der rechten Maustaste auf die hervorgehobenen Abschnitte und wählen Sie dann „Untersuchen“, um die Entwicklertools zu öffnen und das HTML-Dokument anzuzeigen. Wenn Sie den Mauszeiger darüber bewegen, können Sie leicht erkennen, welcher Teil jedem Abschnitt entspricht:

Für dieses Tutorial werde ich CSS-Selektoren verwenden, da sie die einfachste Option darstellen. Wenn diese Methode für Sie neu ist, können Sie sich gerne zuerst diese selbsterklärende Anleitung ansehen.

Bevor wir mit dem Schreiben unseres Skripts beginnen, überprüfen wir, ob die Installation von Puppeteer erfolgreich war:

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")

Hier öffnen wir ein Browserfenster, erstellen eine neue Seite, navigieren zu unserer Ziel-URL und schließen dann den Browser. Der Einfachheit und der visuellen Fehlerbehebung halber öffne ich den Browser im maximierten Modus im Nicht-Headless-Modus.

Da jede Anzeige die gleiche Struktur und die gleichen Daten aufweist, extrahieren wir in unserem Algorithmus alle Informationen für die gesamte Immobilienliste. Am Ende des Skripts durchlaufen wir alle Ergebnisse und fassen sie in einer einzigen Liste zusammen.

Vielleicht ist Ihnen aufgefallen, dass die URL des Eintrags im ersten Screenshot nicht sichtbar war, im zweiten jedoch erwähnt und hervorgehoben wurde. Das liegt daran, dass Sie zur URL der Immobilie weitergeleitet werden, wenn Sie darauf klicken.

// 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)

Wir lokalisieren die URL, indem wir die Ankerelemente auswählen, die das Attribut „data-testid“ mit dem Wert „card-link“ haben. Anschließend wandeln wir das Ergebnis in ein JavaScript-Array um und ordnen jedes Element dem Wert des Attributs „href“ zu.

Die resultierende Liste enthält jedoch jede URL zweimal. Das liegt daran, dass jedes Inserat dasselbe Ankerelement für zwei Abschnitte hat: die Immobilienbilder und die Mietdetails. Wir können dies ganz einfach beheben, indem wir die Datenstruktur „Set“ verwenden:

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

console.log(unique_listings_location)

Für den Immobilienpreis extrahieren wir die „div“-Elemente, die das Attribut „data-testid“ mit dem Wert „card-price“ haben. Auch diese müssen in ein Array konvertiert und dann ihrem Textinhalt zugeordnet werden.

// 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)

Um die Anzahl der Badezimmer und die Wohnfläche zu ermitteln, verwenden wir den Operator für direkte untergeordnete Elemente. Das bedeutet, dass das übergeordnete Element eindeutig identifiziert wird, während das untergeordnete Element eine allgemeinere ID oder einen allgemeineren Klassennamen hat. Abgesehen davon ist die Logik dieselbe wie zuvor:

// 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)

Und schließlich wählen wir für die Adressen der Angebote die „div“-Elemente aus, deren „data-testid“-Attribut auf den Wert „card-address“ gesetzt ist.

// 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)

Nun sollten Sie 5 Listen haben, eine für jede von uns gescrapte Datenangabe. Wie bereits erwähnt, sollten wir diese in einer einzigen Liste zusammenfassen. Auf diese Weise lassen sich die gesammelten Informationen viel einfacher weiterverarbeiten.

// 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)

Das Endergebnis sollte in etwa so aussehen:

[

    {

        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'

    }

]

Vermeiden Sie Bot-Erkennung

Auch wenn das Scraping von Realtor auf den ersten Blick einfach erscheint, kann der Prozess komplexer und anspruchsvoller werden, wenn Sie Ihr Projekt ausweiten. Die Immobilienwebsite setzt verschiedene Techniken ein, um automatisierten Traffic zu erkennen und zu verhindern, sodass Ihr erweiterter Scraper zunehmend blockiert wird.

Realtor verwendet das „Press & Hold“-Modell von CAPTCHA, das von PerimeterX angeboten wird und dafür bekannt ist, dass es aus Ihrem Code heraus fast unmöglich zu lösen ist. Darüber hinaus sammelt die Website auch zahlreiche Browserdaten, um einen eindeutigen Fingerabdruck zu generieren und Sie damit zu verknüpfen.

Zu den gesammelten Browserdaten gehören:

  • Eigenschaften des Navigator-Objekts (deviceMemory, hardwareConcurrency, languages, platform, userAgent, webdriver usw.)
  • Zeit- und Leistungsprüfungen
  • WebGL
  • WebRTC IP-Sniffing
  • und vieles mehr

Eine Möglichkeit, diese Herausforderungen zu bewältigen und weiterhin in großem Umfang zu scrapen, ist die Verwendung einer Scraping-API. Solche Dienste bieten eine einfache und zuverlässige Möglichkeit, auf Daten von Websites wie Realtor.com zuzugreifen, ohne dass Sie einen eigenen Scraper erstellen und warten müssen.

WebScrapingAPI ist ein Beispiel für ein solches Produkt. Sein Proxy-Rotationsmechanismus umgeht CAPTCHAs vollständig, und seine erweiterte Wissensdatenbank ermöglicht es, die Browserdaten zu randomisieren, sodass sie wie von einem echten Nutzer stammen.

Die Einrichtung ist schnell und einfach. Sie müssen lediglich ein Konto registrieren, um Ihren API-Schlüssel zu erhalten. Dieser ist über Ihr Dashboard zugänglich und dient zur Authentifizierung der von Ihnen gesendeten Anfragen.

Da Sie Ihre Node.js-Umgebung bereits eingerichtet haben, können wir das entsprechende SDK nutzen. Führen Sie den folgenden Befehl aus, um es zu Ihren Projektabhängigkeiten hinzuzufügen:

npm install webscrapingapi

Jetzt müssen Sie nur noch die bisherigen CSS-Selektoren an die API anpassen. Die leistungsstarken Extraktionsregeln ermöglichen es, Daten ohne wesentliche Änderungen zu parsen.

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();

Fazit

In diesem Tutorial haben wir eine Schritt-für-Schritt-Anleitung bereitgestellt, wie Sie mit Node.js und Puppeteer Daten von realtor.com scrapen können. Wir haben außerdem Möglichkeiten zur Verbesserung der Zuverlässigkeit und Effizienz des Scrapers erörtert und erläutert, warum die Nutzung eines professionellen Scraper-Dienstes für manche Anwendungsfälle die bessere Option sein kann.

Realtor.com ist eine beliebte und wertvolle Quelle für Immobiliendaten, und mit den Fähigkeiten und Kenntnissen, die Sie in diesem Tutorial erworben haben, sollten Sie nun in der Lage sein, diese Daten mittels Web-Scraping zu extrahieren und in Ihren eigenen Projekten zu nutzen.

Ganz gleich, ob Sie als Immobilienprofi nach einem Wettbewerbsvorteil suchen, als Investor nach neuen Chancen Ausschau halten oder als Hauskäufer auf der Suche nach der perfekten Immobilie sind – Web-Scraping kann Ihnen wertvolle Einblicke und Daten von realtor.com liefern. Wir hoffen, dass dieses Tutorial hilfreich war und Sie nun bereit sind, Ihre Immobilienaktivitäten mit Hilfe von Web-Scraping von realtor.com auf ein neues Niveau zu heben.

Über den Autor
Raluca Penciuc, Full-Stack-Entwickler @ WebScrapingAPI
Raluca PenciucFull-Stack-Entwickler

Raluca Penciuc ist Full-Stack-Entwicklerin bei WebScrapingAPI. Sie entwickelt Scraper, verbessert Umgehungsstrategien und findet zuverlässige Wege, um die Erkennung auf Zielwebsites zu verringern.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.