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

So führen Sie Web-Scraping auf Idealista durch: Ein umfassender Leitfaden (Aktualisierung 2023)

So führen Sie Web-Scraping auf Idealista durch: Ein umfassender Leitfaden (Aktualisierung 2023)

Idealista ist eine der führenden Immobilienwebseiten in Südeuropa und bietet eine Fülle von Informationen zu Immobilien, die zum Verkauf oder zur Miete stehen. Die Seite ist in Spanien, Portugal und Italien verfügbar und listet Millionen von Häusern, Zimmern und Wohnungen auf.

Für Unternehmen und Privatpersonen, die Einblicke in den spanischen Immobilienmarkt gewinnen möchten, kann die Website ein wertvolles Werkzeug sein. Durch Web-Scraping von Idealista können Sie diese wertvollen Informationen extrahieren und auf verschiedene Weise nutzen, beispielsweise für Marktforschung, Lead-Generierung und die Schaffung neuer Geschäftsmöglichkeiten.

In diesem Artikel bieten wir Ihnen eine Schritt-für-Schritt-Anleitung, wie Sie die Website mit TypeScript scrapen können. Wir behandeln die Voraussetzungen, das eigentliche Scrapen von Immobiliendaten und wie Sie den Prozess verbessern können, sowie warum die Verwendung eines professionellen Scrapers besser ist, als einen eigenen zu erstellen.

Am Ende des Artikels verfügen Sie über das Wissen und die Werkzeuge, um Daten aus Idealista zu extrahieren und diese für Ihr Unternehmen sinnvoll zu nutzen.

Voraussetzungen

Bevor wir beginnen, stellen wir sicher, dass wir über die erforderlichen Tools verfügen.

Laden Sie zunächst Node.js von der offiziellen Website herunter und installieren Sie es. Achten Sie dabei darauf, die Long-Term-Support-Version (LTS) zu verwenden. Dadurch wird automatisch auch der Node Package Manager (NPM) installiert, den wir zur Installation weiterer Abhängigkeiten nutzen werden.

Für dieses Tutorial verwenden wir Visual Studio Code als unsere integrierte Entwicklungsumgebung (IDE), aber Sie können jede andere IDE Ihrer Wahl verwenden. Erstellen Sie einen neuen Ordner für Ihr Projekt, öffnen Sie das Terminal und führen Sie den folgenden Befehl aus, um ein neues Node.js-Projekt einzurichten:

npm init -y

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

Als Nächstes müssen wir TypeScript und die Typdefinitionen für Node.js installieren. TypeScript bietet optionale statische Typisierung, die hilft, Fehler im Code zu vermeiden. Führen Sie dazu im Terminal folgenden Befehl aus:

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

Sie können die Installation überprüfen, indem Sie Folgendes ausführen:

npx tsc --version

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. Weitere Informationen zu dieser Datei und ihren Eigenschaften finden Sie in der offiziellen TypeScript-Dokumentation.

Erstellen Sie nun in Ihrem Projekt ein Verzeichnis „src“ 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.

Um schließlich die Daten von der Website zu scrapen, verwenden wir Puppeteer, eine Headless-Browser-Bibliothek für Node.js, mit der Sie einen Webbrowser steuern und programmgesteuert mit Websites interagieren können. Um sie zu installieren, führen Sie diesen Befehl im Terminal aus:

npm install puppeteer

Dies ist sehr empfehlenswert, wenn Sie die Vollständigkeit Ihrer Daten sicherstellen möchten, da viele Websites heutzutage dynamisch generierte Inhalte enthalten. Wenn Sie neugierig sind, können Sie sich vor dem Fortfahren die Puppeteer-Dokumentation ansehen, um sich ein umfassendes Bild von den Möglichkeiten zu machen.

Die Daten finden

Nachdem Sie nun Ihre Umgebung eingerichtet haben, können wir uns mit der Extraktion der Daten befassen. Für diesen Artikel habe ich mich dafür entschieden, die Liste der in einer Region in Toledo, Spanien, verfügbaren Häuser und Wohnungen zu scrapen: https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/.

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

  • die URL;
  • den Titel;
  • den Preis;
  • die Details (Anzahl der Zimmer, Fläche usw.);
  • die Beschreibung

All diese Informationen sind im folgenden Screenshot hervorgehoben:

Wenn Sie für jedes dieser Elemente die Entwicklertools öffnen, können Sie die CSS-Selektoren erkennen, die wir zum Auffinden der HTML-Elemente verwenden werden. Wenn Sie noch nicht so vertraut mit der Funktionsweise von CSS-Selektoren sind, können Sie gerne diesen Leitfaden für Anfänger zu Rate ziehen.

Datenextraktion

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

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

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

Da alle Einträge die gleiche Struktur und die gleichen Daten haben, können wir in unserem Algorithmus alle Informationen für die gesamte Immobilienliste extrahieren. Nach Ausführung des Skripts können wir alle Ergebnisse durchlaufen und zu einer einzigen Liste zusammenfassen.

Um die URLs aller Immobilien zu erhalten, suchen wir die Ankerelemente mit der Klasse „item-link“. Anschließend wandeln wir das Ergebnis in ein JavaScript-Array um und ordnen jedes Element dem Wert des „href“-Attributs zu.

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

Für die Titel können wir dann dasselbe Ankerelement verwenden, nur dass wir diesmal dessen „title“-Attribut extrahieren.

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

Für die Preise suchen wir die „span“-Elemente mit zwei Klassennamen: „item-price“ und „h2-simulated“. Es ist wichtig, die Elemente so eindeutig wie möglich zu identifizieren, damit das Endergebnis nicht verfälscht wird. Auch diese müssen in ein Array umgewandelt und dann ihrem Textinhalt zugeordnet werden.

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

Das gleiche Prinzip wenden wir auf die Objektdetails an, indem wir die „div“-Elemente mit dem Klassennamen „item-detail-char“ analysieren.

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

Und schließlich die Beschreibung der Immobilien. Hier wenden wir einen zusätzlichen regulären Ausdruck an, um alle unnötigen Zeilenumbruchzeichen zu entfernen.

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

Nun sollten Sie 5 Listen haben, eine für jeden Datensatz, den wir gescrapt haben. 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 < 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)

Das Endergebnis sollte wie folgt aussehen:

[

  {

    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ç...'

  }

]

Bot-Erkennung umgehen

Wenn Sie Ihr Skript im Laufe dieses Tutorials mindestens zweimal ausführen, ist Ihnen vielleicht bereits diese lästige Seite aufgefallen:

Idealista nutzt DataDome als Anti-Bot-Schutz, der eine GeeTest-CAPTCHA-Herausforderung beinhaltet. Du musst das Puzzleteil verschieben, bis das Bild vollständig ist, und wirst dann zurück auf deine Zielseite weitergeleitet.

Mit diesem Code kannst du dein Puppeteer-Skript ganz einfach anhalten, bis du die Aufgabe gelöst hast:

await page.waitForFunction(() => {

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

    return pageContent !== null

}, {timeout: 10000})

Dies weist unser Skript an, 10 Sekunden zu warten, bis ein bestimmter CSS-Selektor im DOM erscheint. Das sollte ausreichen, um das CAPTCHA zu lösen und die Navigation abzuschließen.

… Es sei denn, die Idealista-Seite blockiert Sie ohnehin.

An diesem Punkt wurde der Prozess komplexer und anspruchsvoller, und Sie haben Ihr Projekt noch nicht einmal skaliert.

Wie ich bereits erwähnt habe, wird Idealista durch DataDome geschützt. Sie sammeln verschiedene Browserdaten, um einen einzigartigen Fingerabdruck zu generieren und dir zuzuordnen. Wenn sie Verdacht schöpfen, erhältst du die oben genannte CAPTCHA-Herausforderung, die ziemlich schwer automatisch zu lösen ist.

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
  • Aufzeichnung von Mausbewegungen
  • Inkonsistenzen zwischen dem User-Agent und Ihrem Betriebssystem
  • 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. Diese Art von Diensten bietet eine einfache und zuverlässige Möglichkeit, auf Daten von Websites wie Idealista.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 die eines echten Nutzers aussehen.

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

Fazit

In diesem Artikel haben wir Ihnen gezeigt, wie Sie mit TypeScript und Puppeteer Daten von Idealista, einer beliebten spanischen Immobilienwebsite, scrapen können. Wir haben den Prozess der Einrichtung der Voraussetzungen und des Scrapings der Daten durchlaufen und einige Möglichkeiten zur Verbesserung des Codes besprochen.

Das Web-Scraping von Idealista kann wertvolle Informationen für Unternehmen und Privatpersonen liefern. Mit den in diesem Artikel beschriebenen Techniken können Sie Daten wie Immobilien-URLs, Preise und Beschreibungen von der Website extrahieren.

Wenn Sie zudem die Anti-Bot-Maßnahmen und die Komplexität des Scraping-Prozesses vermeiden möchten, kann die Verwendung eines professionellen Scrapers effizienter und zuverlässiger sein als die Erstellung eines eigenen.

Wenn Sie die in diesem Leitfaden beschriebenen Schritte und Techniken befolgen, können Sie das Potenzial des Web-Scrapings von Idealista ausschöpfen und es zur Unterstützung Ihrer geschäftlichen Anforderungen nutzen. Ob für Marktforschung, Lead-Generierung oder die Schaffung neuer Geschäftsmöglichkeiten – das Web-Scraping von Idealista kann Ihnen helfen, der Konkurrenz einen Schritt voraus zu sein.

Ü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.