Kurzfassung: Idealista ist der größte Immobilienmarktplatz in Spanien, Italien und Portugal, verfügt jedoch über einen leistungsstarken Anti-Bot-Stack, der einfache Scraper schnell blockiert. Dieser Leitfaden führt Sie Schritt für Schritt durch den Prozess des Datenscrapings von Idealista in Python und behandelt dabei Website-Mapping, Selenium mit „undetected-chromedriver“, den Umgang mit DataDome, Proxy-Rotation sowie saubere Exporte – einschließlich Maßnahmen zur Produktionsabsicherung, die von Mitbewerbern üblicherweise übersprungen werden.
Einleitung
Wenn Sie schon einmal versucht haben, Daten von Idealista zu scrapen, wissen Sie bereits, dass die Vorgehensweise kurz und brutal ist: ein paar saubere Anfragen senden, blockiert werden, User-Agents tauschen, erneut blockiert werden, ein Captcha sehen und von vorne beginnen. Idealista ist das führende Immobilienportal in Spanien, Portugal und Italien mit Millionen von Verkaufs- und Mietangeboten, was es zu einer Goldgrube für Marktanalysten, Makler und PropTech-Teams macht. Es ist zudem eine der am aggressivsten verteidigten Websites in dieser Kategorie.
Dieser Leitfaden richtet sich an Python-Entwickler mit mittleren Kenntnissen, die ein praxiserprobtes Rezept suchen, nicht nur ein Code-Fragment. Du lernst zunächst den rechtlichen und technischen Kontext kennen, durchläufst dann einen konkreten Selenium-Workflow mit undetected-chromedriver und fügst anschließend Proxys, Captcha-Handling, Deduplizierung und inkrementelles Tracking hinzu – unter Berücksichtigung der Produktionsrealitäten, die die meisten Tutorials auslassen.
Warum Idealista scrapen und welche Daten sind es tatsächlich wert, extrahiert zu werden
Idealista ist einer der größten Immobilienmarktplätze in Südeuropa mit Millionen von Verkaufs- und Mietangeboten auf den spanischen, italienischen und portugiesischen Websites. Für Investorenrecherchen, Vergleichspreismodelle und die Anreicherung von Leads für Agenturen lässt sich diese Reichweite allein über öffentliche APIs kaum nachbilden, weshalb so viele Teams überhaupt erst fragen, wie man Daten von Idealista scrapt.
Wenn Sie ein Scraping planen, entscheiden Sie im Voraus, welche Felder Sie tatsächlich benötigen. Die Objektkarte und die Detailseiten enthalten in der Regel:
- Titel und URL des Angebots (der kanonische
/inmueble/<id>/Slug) - Preis und Währung sowie Preis pro Quadratmeter auf den Detailseiten
- Wohnfläche in m², Anzahl der Zimmer und Badezimmer
- Beschreibungstext, Datum der Anzeige und Datum der letzten Aktualisierung
- Art des Anbieters (Privatperson vs. Agentur), mit Telefon- und Kontakt-Schaltflächen
- Fotos, Grundrisse und manchmal Links zu virtuellen Rundgängen
- Ungefähre Koordinaten und Metadaten zur Nachbarschaft
Die italienischen (idealista.it) und portugiesischen (idealista.pt) Websites entsprechen in der Regel dem spanischen Layout, sodass ein einziges Scraper-Design mit geringfügigen Anpassungen der Selektoren in der Regel für alle drei Websites geeignet ist. Wir werden auf diese Unterschiede im Abschnitt zur Fehlerbehebung zurückkommen.
Ist das Scraping von Idealista legal? Grundregeln zur Compliance
Öffentlich zugängliche Angebotsdaten gelten im Allgemeinen als zulässig, wenn sie in angemessenem Umfang erfasst werden, doch die Nutzungsbedingungen von Idealista und die DSGVO der EU ändern die Lage, sobald Sie mit personenbezogenen Daten in Berührung kommen. Maklernamen, Telefonnummern und E-Mail-Adressen sind gemäß der DSGVO personenbezogene Daten, sodass deren Speicherung in großem Umfang in der Regel eine dokumentierte Rechtsgrundlage, Aufbewahrungsfristen und einen Weg zur Datenlöschung erfordert.
Praktische Leitlinien: Halten Sie robots.txt, drosseln Sie die Zugriffsrate aggressiv, meiden Sie Bereiche, die eine Anmeldung erfordern, und entfernen Sie persönliche Kontaktdaten aus allen Datensätzen, die Sie weiterverbreiten. Betrachten Sie diesen Abschnitt als Orientierungshilfe und nicht als Rechtsberatung, und lassen Sie sensible Inhalte vor der Produktion von Ihrem Rechtsbeistand prüfen. Die rechtliche Lage ist hier tatsächlich umstritten, überprüfen Sie daher den aktuellen Geltungsbereich der DSGVO für Ihren spezifischen Anwendungsfall, bevor Sie einen Scraper in großem Umfang einsetzen.
Wie Idealista Bots erkennt: DataDome, Fingerprinting und Ratenbegrenzungen
In den meisten öffentlichen Berichten wird Idealistas Interstitial-Captcha DataDome zugeschrieben, einem kommerziellen Dienst zur Bot-Abwehr. Betrachten Sie diese Zuschreibung eher als Konsens der Community denn als offizielle Stellungnahme, da Idealista seinen Erkennungsstack nicht veröffentlicht.
Die Erkennung erfolgt in mehreren Schichten, und das Verständnis jeder einzelnen Schicht entscheidet darüber, ob ein Scraper eine Woche überlebt oder innerhalb einer Stunde blockiert wird:
- TLS- und JA3-Fingerprinting. Einfache
requestsund viele HTTP-Bibliotheken erzeugen eine TLS-Handshake-Signatur, die sich leicht von einer echten Chrome-Sitzung unterscheiden lässt. Selbst mit einem perfekten User-Agent verrät dich die Reihenfolge der Verschlüsselungsalgorithmen. - Kohärenz der Header. Bot-Erkennungs-Engines prüfen, ob
Accept,Accept-Language,sec-ch-uaundUser-Agentstimmen miteinander übereinstimmen. Ein Chrome-120-User-Agent in Verbindung mit einem fehlendensec-ch-ua-platformHeader ist ein verräterisches Zeichen. - JavaScript-Herausforderungen. DataDome stellt eine kleine JS-Nutzlast bereit, die
navigator.webdriver, Canvas-Hashes, WebGL-Renderer und Timing-Signale. Headless Chrome und Standard-Selenium scheitern standardmäßig bei mehreren davon. - Verhaltens- und IP-Signale. Geschwindigkeit, mausfreie Navigation, ASN-Bereiche von Rechenzentren und wiederverwendete Cookies fließen alle in eine Risikobewertung ein, die das Captcha auslöst.
Ihr Bot benötigt einen echten Browser-Fingerabdruck, plausible Header, private oder mobile IPs sowie ein menschenähnliches Tempo. Keine einzelne Maßnahme reicht aus.
Auswahl eines Scraping-Stacks: requests/HTTPX vs. Selenium vs. eine Scraping-API
Es gibt keine allgemeingültige Antwort darauf, wie man Daten von Idealista in großem Umfang scrapt; die richtige Wahl hängt vom Volumen, dem Budget und davon ab, wie viel JavaScript-Rendering Sie verkraften können. Hier ist eine kurze Entscheidungsmatrix, die Sie in ein Planungsdokument einfügen können.
|
Ansatz |
Am besten geeignet für |
Geschwindigkeit |
DataDome-Resistenz |
Wartung |
|---|---|---|---|---|
|
|
Kleine einmalige Abfragen |
Schnell |
Niedrig |
Gering, bis blockiert |
|
|
Mittleres Scraping, asynchrone Verarbeitung |
Sehr schnell |
Niedrig bis mittel |
Mäßig |
|
Selenium + undetected-chromedriver |
Zuverlässige Extraktion pro Seite |
Langsam |
Mittel |
Hoch (Treiberabweichung) |
|
Verwaltete Scraping-API |
Produktionsmaßstab, automatisiert |
Variabel |
Hoch |
Niedrig |
Reine HTTP-Stacks sind die kostengünstigste Lösung, solange sie funktionieren, versagen jedoch, sobald Idealista zu einer JS-Herausforderung wird. Selenium mit undetected-chromedriver bietet dir einen echten Browser-Fingerabdruck und DOM-Ausführung, ist dafür aber deutlich langsamer und speicherintensiver. Eine verwaltete API verbirgt die Proxy- und Challenge-Lösungsschicht vollständig, was die richtige Entscheidung ist, sobald du über eine einzelne Maschine hinauswächst. Die meisten Produktionsteams kombinieren letztendlich beides: einen schnellen HTTP-Pfad für einfache Seiten, einen Browser-Fallback für gehärtete Seiten und eine Scraping-API als Sicherheitsnetz.
Einrichten Ihres Python-Projekts und der Abhängigkeiten
Sie benötigen Python 3.10 oder neuer, eine saubere virtualenv-Umgebung und festgelegte Abhängigkeiten. Das Frontend von Idealista ändert sich häufig, daher erleichtert das Festlegen von Versionen später die Diagnose von Regressionen.
python -m venv .venv
source .venv/bin/activate
pip install selenium==4.* undetected-chromedriver selenium-wire httpx parsel tenacity python-dotenvEin praktisches Layout:
idealista-scraper/
├── .env # proxy credentials, API keys
├── config.py # constants, base URLs
├── scraper/
│ ├── driver.py # uc.Chrome factory + waits
│ ├── crawl.py # provinces → municipalities → listings
│ └── parse.py # XPath/CSS extractors
├── storage.py # JSON/CSV/SQLite writers
└── main.pyFixieren Sie die Hauptversion von Chrome an Ihre installierte undetected-chromedriver Build; Nichtübereinstimmungen sind die häufigste Ursache für stille Abstürze.
Zuordnung der URL-Struktur von Idealista: Startseite, Provinzen, Gemeinden, Suche, Immobilien
Bevor Sie auch nur einen einzigen Selektor schreiben, gehen Sie die Website manuell durch. Das URL-Schema von Idealista ist ziemlich regelmäßig, sobald man das Muster erkannt hat, und eine klare mentale Karte verhindert, dass Sie dieselben Knoten erneut crawlen.
Die Hierarchie sieht in etwa so aus:
- Startseite:
https://www.idealista.com/(und.it,.ptfür die italienische und portugiesische Version) - Verzeichnis der Provinzen: verlinkt am Ende der Startseite
- Gemeindeverzeichnis: unter jeder Provinz eine Seite mit einer Liste der Gemeinden
- Angebotsseiten:
/venta-viviendas/<municipality>/zum Verkauf,/alquiler-viviendas/<municipality>/zu vermieten (die URL-Strukturen für Vermietungen sowie in IT/PT entsprechen in der Regel dieser, bitte überprüfen Sie dies jedoch zunächst auf einer Live-Seite) - Paginierung:
pagina-2.htm,pagina-3.htm, angehängt an die URL des Eintrags - Objektdetails:
/inmueble/<id>/, die kanonische eindeutige Angebots-ID - Sortierung nach Aktualität:
?ordenado-por=fecha-publicacion-desc, um neu gelistete Immobilien zuerst anzuzeigen
Verinnerlichen Sie diesen inmueble/<id> Slug; der Rest des Artikels verwendet ihn als Duplikatsschlüssel und Dreh- und Angelpunkt für die Änderungsverfolgung. Eine solide CSS-Selektor-Referenz ist hier von unschätzbarem Wert, wenn sich Selektoren verschieben.
So scrapen Sie Daten von Idealista mit Selenium und undetected-chromedriver
Mit der URL-Zuordnung in der Hand können Sie den eigentlichen Scraper aufsetzen. Der Plan: Starten Sie ein gepatchtes Chrome über undetected-chromedriver, navigieren Sie zur Startseite und verwenden Sie explizite Wartezeiten, um sicherzustellen, dass das DOM gerendert wurde, bevor Sie es abfragen. Die nächsten vier Schritte bauen den Crawler in einem Top-Down-Durchlauf auf, von Provinzen über Gemeinden bis hin zu Objektkarten und Paginierung.
Schritt 1: Extrahieren der vollständigen Liste der Provinzen von der Startseite
Die spanische Startseite zeigt im Fußbereich ein Verzeichnis der Provinzen an. Wir erfassen jeden Anker innerhalb dieses Blocks, speichern den sichtbaren Namen und behalten die absolute URL für den nächsten Schritt.
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def make_driver():
opts = uc.ChromeOptions()
opts.add_argument("--window-size=1366,900")
# use_subprocess=True is currently required to avoid a destructor
# bug in some undetected-chromedriver builds; verify against the
# upstream repo before pinning, since package internals change often.
return uc.Chrome(options=opts, use_subprocess=True)
def fetch_provinces(driver):
driver.get("https://www.idealista.com/")
WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "div.locations-list"))
)
anchors = driver.find_elements(
By.XPATH, "//div[contains(@class,'locations-list')]//a"
)
return {a.text.strip(): a.get_attribute("href") for a in anchors if a.text.strip()}Der erste Aufruf wird mit ziemlicher Sicherheit auf ein DataDome-Captcha stoßen, umgeben Sie ihn daher beim ersten Durchlauf mit einem Hook zur manuellen Lösung (wird später behandelt). Sobald Ihre Sitzung über ein sauberes Cookie verfügt, läuft der Rest des Crawls in der Regel reibungslos ab.
Schritt 2: Crawlen Sie jede Provinz nach ihren Gemeinden
Jede Provinzseite listet ihre Gemeinden in einem location_list Block an. Wir durchlaufen das Wörterbuch aus Schritt 1 und fügen den Namen und die URL jeder Gemeinde unter ihrer übergeordneten Provinz ein.
def fetch_municipalities(driver, provinces):
out = {}
for name, url in provinces.items():
driver.get(url)
WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.ID, "location_list"))
)
anchors = driver.find_elements(By.XPATH, "//ul[@id='location_list']//a")
out[name] = {
"url": url,
"municipalities": [
{"name": a.text.strip(), "url": a.get_attribute("href")}
for a in anchors if a.text.strip()
],
}
time.sleep(random.uniform(2.5, 6.0)) # polite pacing
return outZwei Dinge sind erwähnenswert: Zufällige Pausen ahmen menschliches Surfen überzeugender nach als feste Verzögerungen, und du solltest dieses verschachtelte Wörterbuch nach jeder Provinz auf der Festplatte speichern, damit ein Absturz bei Provinz Nummer 30 dich nicht die vorherigen 29 kostet.
Schritt 3: Immobilienkarten auswerten (Titel, Preis, Fläche, Beschreibung, URL)
Listenseiten rendern einen article.item Knoten pro Immobilie mit strukturierten untergeordneten Elementen für die kanonischen Felder. Die folgenden XPath-Muster verwenden contains(@class, ...) anstelle strikter Gleichheit, da Idealista gelegentlich Modifikatorklassen an seine Karten anhängt.
def parse_listing_page(driver):
cards = driver.find_elements(By.XPATH, "//article[contains(@class,'item')]")
rows = []
for c in cards:
try:
link = c.find_element(By.XPATH, ".//a[contains(@class,'item-link')]")
url = link.get_attribute("href")
title = link.text.strip()
price = c.find_element(
By.XPATH, ".//span[contains(@class,'item-price')]"
).text.strip()
details = [
d.text.strip() for d in c.find_elements(
By.XPATH, ".//span[contains(@class,'item-detail-char')]/span"
)
]
description = c.find_element(
By.XPATH, ".//div[contains(@class,'item-description')]"
).text.strip()
rows.append({
"id": url.rstrip("/").split("/")[-1],
"url": url, "title": title, "price": price,
"details": details, "description": description,
})
except Exception:
# Sponsored or malformed cards: skip rather than abort.
continue
return rowsZwei Hinweise zur Produktion. Erstens mischt Idealista Anzeigenkarten unter, die fast identisch mit organischen Karten aussehen; die try/except um jede Karte herum verhindert, dass ein fehlerhafter Knoten die Seite lahmlegt. Zweitens ändern sich Selektoren; rechnen Sie damit, diese XPaths alle paar Monate zu aktualisieren. Speichern Sie sie in einem einzigen parse.py Modul, damit der Vergleich einfach ist.
Schritt 4: Verfolgen Sie die Paginierung über den Link „Siguiente“
Idealista verwendet ein numerisches Paginierungsschema mit einem Siguiente („Weiter”)-Link, der in li.next. Einige Tutorials greifen rekursiv auf die nächste URL zu, bis diese verschwindet, doch durch unbegrenzte Rekursion stoßen Sie bei dicht besiedelten Gemeinden schnell an Ratenbegrenzungen und erreichen die Rekursionsgrenze von Python. Begrenzen Sie stattdessen die Schleife.
MAX_PAGES = 40
def crawl_municipality(driver, start_url, max_pages=MAX_PAGES):
rows, url, page = [], start_url, 0
while url and page < max_pages:
driver.get(url)
WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.XPATH, "//main"))
)
rows.extend(parse_listing_page(driver))
try:
next_link = driver.find_element(
By.XPATH, "//li[contains(@class,'next')]/a"
)
url = next_link.get_attribute("href")
except Exception:
url = None
page += 1
time.sleep(random.uniform(3.0, 7.0))
return rowsEine Obergrenze von 40 Seiten entspricht in etwa Idealistas eigener Grenze für die Tiefenpaginierung und hält jeden Worker im Rahmen. Wenn du wirklich mehr benötigst, teile die Suche nach Preisklassen oder Immobilientypen auf und führe diese Unterabfragen parallel aus, anstatt tiefer in einen einzelnen Ergebnissatz einzutauchen.
Lösen von DataDome-Captchas während der Sitzung ohne Statusverlust
Jeder, der lernt, wie man Daten von Idealista scrapt, wird irgendwann auf das DataDome-Interstitial stoßen. Die gute Nachricht, die in mehreren Scraper-Communities anekdotisch bestätigt wurde, ist, dass die Herausforderung, sobald man sie in einer Sitzung gelöst hat, für den Rest dieser Browsersitzung in der Regel nicht mehr erscheint. Darauf kannst du dich mit ein paar konkreten Taktiken verlassen.
Die einfachste ist ein Hook zur manuellen Lösung für die Entwicklung:
def open_with_captcha_pause(driver, url):
driver.get(url)
if "captcha" in driver.page_source.lower() or "datadome" in driver.page_source.lower():
input("Solve the captcha in the browser, then press Enter to continue...")Für alles, was über eine einmalige Lösung hinausgeht, steigere das Niveau:
- Persistentes Profil. Übergeben
--user-data-dir=./chrome-profileso, dass Cookies und das DataDome_ddCookie die Läufe überdauern. - Wechseln Sie die IP-Adresse nach einer Herausforderung. Ein Captcha auf einer privaten IP-Adresse ist wiederherstellbar; ein Captcha, das auf derselben IP-Adresse wiederholt auftritt, bedeutet in der Regel, dass sie gesperrt ist. Wechseln Sie zu einem neuen Ausgang und versuchen Sie es erneut.
- Verlangsamen Sie den Vorgang. Fügen Sie vor einem erneuten Versuch nach einer Challenge eine längere zufällige Wartezeit (30 bis 90 Sekunden) ein, anstatt die gleiche URL ununterbrochen anzufragen.
- Eskalieren Sie an einen verwalteten Solver. Wenn Durchsatz wichtiger ist als Kontrolle, leiten Sie die Anfrage über eine Scraping-API weiter, die Fingerprinting und Herausforderungen auf ihrer Seite abwickelt.
Betrachten Sie das Captcha als Signal dafür, dass Ihr Fingerabdruck, Ihre IP-Adresse oder Ihr Tempo einen Schwellenwert überschritten haben, und nicht als einzelnes Popup, das Sie einfach wegklicken können.
Skalierung ohne Blockierung: Proxys, Header und Ratenkontrolle
Das Schwierige daran, Daten von Idealista im Produktionsvolumen zu scrapen, ist nicht das Parsen des HTML-Codes, sondern den Blockierungen einen Schritt voraus zu sein. Sobald Ihr Prototyp funktioniert, deckt die Skalierung neue Fehlerquellen auf. IP-Adressen von Rechenzentren, die Ihre ersten 200 Anfragen überstanden haben, werden massenhaft herausgefordert, identische Header bei allen Workern fallen auf, und eng synchronisierte Anfragen wirken wie ein koordinierter Bot.
Stufen Sie Ihre Abwehrmaßnahmen in dieser Reihenfolge auf und erhöhen Sie die Komplexität erst dann, wenn die vorherige Stufe nicht mehr funktioniert.
1. Privathaushalts- oder Mobil-Proxys, geotargetet. Der Traffic von Idealista wird von spanischen, italienischen und portugiesischen Verbrauchern dominiert. Privathaushalts-IPs aus diesen Ländern fügen sich nahtlos ein; ein ASN eines US-Rechenzentrums hingegen nicht. Mit selenium-wire:
from seleniumwire.undetected_chromedriver import Chrome
seleniumwire_options = {
"proxy": {
"http": "http://user:pass@es.proxy.example:8000",
"https": "http://user:pass@es.proxy.example:8000",
"no_proxy": "localhost,127.0.0.1",
}
}
driver = Chrome(seleniumwire_options=seleniumwire_options, use_subprocess=True)2. Header-Rotation. Wechseln Sie zyklisch zwischen einem kleinen Pool realistischer Chrome-12x-Header (passend User-Agent, sec-ch-uaund Accept-Language). Halten Sie sie konsistent; nicht übereinstimmende Client-Hinweise werden schneller markiert als jeder einzelne fehlerhafte Header.
3. Begrenzung der Parallelität. Begrenzen Sie die Anzahl der Worker pro IP auf 1, pro Region auf 4 bis 8 und pro Crawl auf die Anzahl, die Ihr Proxy-Tarif unterstützt. Fügen Sie verzögerte Intervalle von 3 bis 10 Sekunden zwischen den Seitenabrufen ein, damit Ihr Traffic nicht pulsiert.
4. Eine verwaltete Scraping-API als Sicherheitsnetz. Sobald Sie mehrere tausend Seiten pro Tag durchlaufen, kostet die Wartung Ihres eigenen Fingerprinting-Stacks mehr, als er einspart. Eine verwaltete Scraper-API übernimmt die IP-Rotation, die Lösung von Sicherheitsabfragen und die Wiederholungslogik hinter einem einzigen Endpunkt, sodass Sie Ihren Parsing-Code beibehalten und lediglich die Abrufebene austauschen können. Betrachten Sie dies als Ausweichlösung und nicht als Standard.
Speichern, Deduplizieren und Exportieren des gescrapten Eigenschaftsdatensatzes
Das Ausgeben von Zeilen auf stdout ist für eine Demo in Ordnung, in der Produktion jedoch nutzlos. Stream schreibt die Daten während des Vorgangs auf die Festplatte, sodass ein Absturz in der achten Stunde die ersten sieben Stunden nicht löscht.
import json, sqlite3
def upsert_sqlite(db_path, rows):
conn = sqlite3.connect(db_path)
conn.execute(
"CREATE TABLE IF NOT EXISTS listings ("
"id TEXT PRIMARY KEY, url TEXT, title TEXT, price TEXT, "
"details TEXT, description TEXT, scraped_at TEXT)"
)
conn.executemany(
"INSERT OR REPLACE INTO listings VALUES (?,?,?,?,?,?,datetime('now'))",
[(r["id"], r["url"], r["title"], r["price"],
json.dumps(r["details"]), r["description"]) for r in rows],
)
conn.commit(); conn.close()Verwenden Sie den inmueble/<id> Slug als Primärschlüssel; Titel und Preise ändern sich, IDs nicht. Für schlankere Pipelines funktioniert „Append-only“ JSONL plus ein täglicher Deduplizierungsdurchlauf auf denselben Schlüssel gut.
Planmäßige Verfolgung neu gelisteter Idealista-Immobilien
Die meisten Teams, die fragen, wie man regelmäßig Daten von Idealista scrapt, interessieren sich weniger für einen einmaligen Massendump als vielmehr dafür, was in den letzten 24 Stunden neu erschienen ist. Makler, Investmentfonds und Lead-Generierungstools wollen alle ein aktuelles Delta, nicht das vollständige Archiv. Idealista stellt eine Sortierung nach Aktualität mit ?ordenado-por=fecha-publicacion-desc, was die Grundlage für einen schlanken Workflow zur Änderungsverfolgung bildet.
Das Prinzip ist einfach: Führen Sie den Crawler für jede beobachtete Gemeinde auf die nach Aktualität sortierte URL an, vergleichen Sie die resultierenden IDs mit Ihrem letzten Lauf und geben Sie nur die neuen Zeilen aus.
def diff_new_listings(rows, seen_ids_path):
seen = set(pathlib.Path(seen_ids_path).read_text().splitlines()) if pathlib.Path(seen_ids_path).exists() else set()
new_rows = [r for r in rows if r["id"] not in seen]
pathlib.Path(seen_ids_path).write_text(
"\n".join(seen | {r["id"] for r in new_rows})
)
return new_rowsPlanen Sie den Job stündlich über Cron oder Airflow, lassen Sie sich über neue Zeilen per Slack oder E-Mail benachrichtigen, und schon haben Sie einen funktionierenden Immobilien-Radar ohne eigenes Backend.
Fehlerbehebung: leere Ergebnisse, veraltete Selektoren und ChromeDriver-Abstürze
Einige wenige Muster sind für die meisten Fehler verantwortlich, die Leser melden.
use_subprocessMacke. Aktuelleundetected-chromedriverVeröffentlichungen erfordernuse_subprocess=Trueauf einigen Plattformen, um eine Destruktor-Warnung zu vermeiden, die den Treiber beschädigen kann. Überprüfen Sie dies anhand des Upstream-Repos, da sich die Abhilfe je nach Version ändert.NoSuchElementExceptionauf Karten. In der Regel hat Idealista einen Klassennamen ausgetauscht. Überprüfen Sie das DOM erneut und bevorzugen Siecontains(@class, ...)einer strengen Gleichheit./en/Layoutunterschiede. Die englische Locale liefert ein leicht abweichendes DOM. Fixiere die tatsächlich gewünschte Locale und behalte Selektoren pro Locale bei, wenn du zwischen Websites wechselst.- Chrome und Treiber stimmen nicht überein. Fixiere beide. Ein
SessionNotCreatedExceptionbedeutet fast immer, dass der gepatchte Treiber und Ihr installiertes Chrome um eine Hauptversion voneinander abweichen.
Wichtige Erkenntnisse
- Der Blocking-Stack von Idealista kombiniert DataDome-Herausforderungen, TLS-Fingerprinting und IP-Reputation, sodass eine einzelne Taktik wie das Rotieren von User-Agents im großen Maßstab nicht ausreicht.
- Verwenden Sie den
inmueble/<id>Slug als Duplikatschlüssel und primäre Kennung; Titel und Preise ändern sich, IDs nicht. - Begrenzen Sie Ihre Paginierung (auf etwa 40 Seiten pro Gemeinde) und teilen Sie tiefergehende Abfragen nach Preisklassen oder Immobilientypen auf, anstatt endlos zu rekurieren.
- Schichten Sie Ihre Abwehrmaßnahmen in folgender Reihenfolge: Real-Browser-Fingerabdruck, geotargetierte private IPs, Header-Rotation, höfliches Pacing und schließlich eine verwaltete Scraping-API als Fallback.
- Verfolgen Sie neue Angebote, indem Sie nach
fecha-publicacion-descund den Vergleich der IDs mit Ihrem letzten Durchlauf; genau das macht einen Scraper zu einem nützlichen Produkt.
FAQ
Ist das Scraping von Idealista legal, und wie gilt die DSGVO für die Kontaktdaten von Maklern?
Öffentliche Angebotsdaten dürfen im Allgemeinen in angemessenem Umfang rechtmäßig erfasst werden, aber Maklernamen, Telefonnummern und E-Mail-Adressen sind personenbezogene Daten im Sinne der DSGVO und erfordern eine dokumentierte Rechtsgrundlage, Aufbewahrungsfristen und einen Löschpfad. Das Speichern oder Weiterverbreiten von Maklerkontakten in großem Umfang ohne diese Kontrollen ist der riskanteste Teil jeder Idealista-Pipeline. Konsultieren Sie einen Rechtsbeistand für länderspezifische Hinweise.
Bietet Idealista eine offizielle API für Immobiliendaten an?
Idealista veröffentlicht keine allgemeine API für öffentliche Immobilienanzeigen. Das Entwicklerprogramm ist eher auf Partnerintegrationen und Anzeigenplatzierung ausgerichtet als auf offenen Datenzugriff. Für die meisten Analyse- oder Forschungszwecke sind das Scraping der öffentlichen Website oder der Kauf eines verwalteten Immobiliendatensatzes die realistischen Optionen. Überprüfen Sie das aktuelle Entwicklerportal direkt, bevor Sie davon ausgehen, dass ein bestimmter Endpunkt verfügbar ist.
Warum zeigt Idealista weiterhin ein DataDome-Captcha an, selbst wenn ich „undetected-chromedriver“ verwende?
„undetected-chromedriver“ behebt nur ein Signal, das navigator.webdriver Flag und eine Handvoll Chrome-Interna. DataDome wertet zudem TLS-Fingerabdrücke, Header-Kohärenz, IP-Reputation und Verhaltens-Pacing aus. Wenn sich Ihre IP in einem markierten Rechenzentrumsbereich befindet oder Ihre Header inkonsistent sind, wird die Challenge weiterhin ausgelöst. Fügen Sie zunächst Residential-Proxys und ein langsameres Pacing hinzu.
Sollte ich für Idealista Selenium, HTTPX mit Parsel oder eine verwaltete Scraping-API verwenden?
Das hängt vom Umfang ab. Für einige hundert Seiten ist HTTPX mit Parsel am schnellsten. Für eine zuverlässige Extraktion pro Seite mit JS-Rendering ist Selenium mit undetected-chromedriver der bewährte Mittelweg. Bei mehr als einigen tausend Seiten pro Tag entfallen durch eine verwaltete Scraping-API der Proxy- und der Challenge-Lösungsaufwand, und sie ist in der Regel günstiger als die Wartung eines eigenen Fingerprinting-Stacks.
Kann derselbe Scraper auf den italienischen und portugiesischen Seiten von Idealista sowie bei Mietangeboten eingesetzt werden?
Im Großen und Ganzen ja. Die italienischen (idealista.it) und portugiesischen (idealista.pt) Seiten haben in der Regel das gleiche Layout wie die spanische Seite, und die Mietangebote folgen einem alquiler-viviendas Muster, das venta-viviendas. Überprüfen Sie die Selektoren anhand der Live-Seiten, da Idealista gelegentlich A/B-Tests mit lokalspezifischen Anpassungen bei Kartenlayouts und Paginierung durchführt.
Fazit
Herauszufinden, wie man Daten von Idealista scrapt, ist vor allem eine Übung darin, die mehrschichtigen Abwehrmechanismen zu respektieren, die die Website im Laufe der Jahre aufgebaut hat. Stellen Sie die URL-Zuordnung richtig ein, verwenden Sie einen echten Browser-Fingerabdruck mit undetected-chromedriver, binden Sie Ihre Paginierung ein, deduplizieren Sie auf der inmueble/<id> Slug und leiten Sie Schreibvorgänge auf die Festplatte um, damit ein Absturz Sie nie einen kompletten Durchlauf kostet. Betrachten Sie DataDome-Herausforderungen als Signal, dass Ihre IP, Ihr Fingerabdruck oder Ihr Pacing eine Grenze überschritten haben, und nicht als Popup, das Sie wegklicken können. Sobald Sie vom Prototyp in den Produktionsbetrieb übergehen, macht sich das mehrschichtige Playbook (Residential-Proxys, Geo-Targeting, Header-Rotation, Retry-Logik) fast sofort bezahlt.
Wenn Sie die Proxy-Einrichtung und das Lösen von Herausforderungen lieber ganz überspringen möchten, übernimmt die Scraper-API von WebScrapingAPI die Abrufebene hinter einem einzigen Endpunkt und gibt HTML zurück, das Sie direkt in die oben genannten Parser einfügen können. So oder so bietet Ihnen der hier beschriebene Workflow einen klaren Weg von einem Prototyp auf einem einzelnen Rechner zu einer geplanten Pipeline, die neue spanische, italienische und portugiesische Angebote in einem sinnvollen Rhythmus verfolgt.




