Zillow est l'une des plateformes immobilières les plus visitées du web, et ses pages d'annonces contiennent exactement les données structurées qui alimentent le suivi des prix, la recherche de marché et l'analyse d'investissement : le prix demandé, le nombre de chambres, de salles de bain, la surface intérieure, le type de bien et l'adresse postale. Pour quiconque étudie un marché local, ces données publiques d'annonces sont la matière première, et les collecter manuellement sur des dizaines de biens est lent et sujet aux erreurs.

Ce guide vous montre comment extraire des données de Zillow avec Python de manière fiable. Vous construisez un script léger et exécutable qui récupère les pages Zillow rendues via la Crawling API, collecte les liens de propriétés depuis une page de recherche, analyse les champs souhaités avec BeautifulSoup, gère la pagination et exporte des fichiers JSON et CSV propres. L'ensemble du tutoriel se limite aux données d'annonces publiques, et la section légalité vers la fin n'est pas du remplissage, lisez-la avant de pointer ce script sur un volume réel.

Ce que vous allez construire

Un script Python qui prend une URL de recherche publique Zillow pour un emplacement, collecte les liens vers les pages de propriétés, récupère chaque annonce rendue via la Crawling API et extrait un enregistrement structuré par propriété. L'exemple de référence porte sur des propriétés à vendre à Columbia Heights, Washington, DC. Les champs extraits sont :

  • Prix le prix demandé pour la propriété.
  • Chambres le nombre de chambres.
  • Salles de bain le nombre de salles de bain.
  • Surface la surface intérieure du logement en pieds carrés.
  • Adresse l'adresse postale affichée sur l'annonce.
  • Type le type de bien, comme condominium, maison de ville ou maison individuelle.
  • Lien l'URL canonique de la page de propriété.

Pourquoi une requête simple échoue sur Zillow

Si vous demandez une URL de recherche ou d'annonce Zillow avec un client HTTP ordinaire, vous obtenez une réponse avec le statut 200 et seulement une fraction des données dans le corps. Deux facteurs jouent contre vous. Premièrement, Zillow charge la plupart de ses résultats de recherche et des détails d'annonces dans le navigateur via JavaScript et Ajax, donc le HTML initial est une coquille vide qui ne se remplit qu'après l'exécution des scripts de la page. Extraire les liens de propriétés de cette première réponse ne vous donne qu'une poignée de cartes au lieu du jeu complet. Deuxièmement, Zillow détecte rapidement le trafic automatisé : les adresses IP de centre de données et les schémas de requêtes qui ne ressemblent pas à un vrai navigateur se voient limités en débit, bloqués par IP ou soumis à un défi avant même d'atteindre le contenu rendu.

Un scraper Zillow fonctionnel a donc besoin de deux choses en une seule requête : un navigateur qui rende réellement la page, et une adresse IP que la plateforme identifie comme un vrai visiteur. Vous pouvez assembler cela vous-même avec un navigateur sans tête et un pool de proxies résidentiels rotatifs, mais les connecter et les maintenir en bon état représente l'essentiel du travail. La Crawling API regroupe les deux en un seul appel : vous lui envoyez l'URL avec un token JavaScript, elle rend la page derrière une IP de confiance et vous renvoie le HTML complet à analyser.

Pourquoi le token JS

Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend d'abord la page dans un vrai navigateur. Zillow remplit ses résultats de recherche et ses champs d'annonces côté client, vous avez donc besoin du token JS ici. Le token normal renvoie la même coquille vide qu'une simple requête, et il n'y a pratiquement rien d'utile à en extraire.

Prérequis

Quelques éléments doivent être en place avant d'écrire du code. Aucun ne prend longtemps.

Python de base. Vous devez être à l'aise pour écrire et exécuter un script Python et installer des paquets avec pip. Si vous êtes nouveau côté analyse, le guide BeautifulSoup est un bon complément à ce tutoriel.

Python 3.8 ou supérieur. Vérifiez votre version avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda, et assurez-vous que Python est dans votre PATH.

Un compte Crawlbase et un token JS. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token JavaScript (JS) depuis la page de documentation du compte. Crawlbase inclut jusqu'à 20 000 requêtes gratuites pour commencer, ce qui est largement suffisant pour ce guide. Traitez le token comme un mot de passe : il authentifie vos requêtes, gardez-le hors du contrôle de version.

Configurer le projet

Créez un environnement virtuel pour isoler les dépendances du projet, puis installez les bibliothèques dont le scraper a besoin.

bash
python --version

python -m venv zillow_env
source zillow_env/bin/activate

pip install crawlbase beautifulsoup4

Sur Windows, activez l'environnement avec zillow_env\Scripts\activate à la place de la ligne source. Deux dépendances font le travail : crawlbase est le client officiel pour la Crawling API, et beautifulsoup4 analyse le HTML renvoyé afin que vous puissiez extraire les champs individuels par sélecteur CSS. Les modules json et csv font partie de la bibliothèque standard, il n'y a donc rien de plus à installer pour l'étape d'exportation.

Étape 1 : récupérer une page Zillow rendue

Commencez par obtenir une page complète. Importez la classe CrawlingAPI, initialisez-la avec votre token JS et demandez une URL de recherche Zillow. Zillow charge les résultats de façon asynchrone, passez donc ajax_wait et page_wait pour attendre le contenu dynamique avant la capture de la page. Vérifier le cb_status (legacy pc_status) de Crawlbase avant d'analyser permet de rendre les échecs visibles plutôt que silencieux.

python
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

OPTIONS = {
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/122.0",
    "ajax_wait": "true",
    "page_wait": 5000,
}

def crawl(page_url):
    response = api.get(page_url, OPTIONS)
    if response["headers"]["cb_status"] == "200":
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['headers']['cb_status']}")
    return None

if __name__ == "__main__":
    serp_url = "https://www.zillow.com/columbia-heights-washington-dc/sale/"
    html = crawl(serp_url)
    print(html[:500] if html else "No HTML returned")

Les deux options d'attente sont importantes pour une cible rendue côté client comme Zillow. ajax_wait demande à l'API d'attendre la fin du chargement du contenu asynchrone, et page_wait maintient le délai pendant un nombre fixe de millisecondes après le chargement afin que les cartes de rendu tardif apparaissent avant la capture. Cinq secondes est un bon point de départ ; augmentez si les résultats reviennent incomplets. Exécutez le script avec python zillow_scraper.py et vous devriez voir le vrai balisage de recherche Zillow, pas la coquille vide d'une simple requête. Cela confirme que le rendu fonctionne avant d'écrire le moindre sélecteur.

Crawlbase Zillow Scraper

Zillow nécessite une page rendue derrière une IP de confiance, en un seul appel, ce que les options ajax_wait et page_wait ci-dessus configurent exactement. La Crawling API prend un token JS, exécute la page dans un vrai navigateur, fait tourner les IP résidentielles côté serveur et vous remet le HTML complet, vous évitant ainsi de gérer votre propre flotte sans tête et un pool de proxies. Pointez-la sur une page de recherche publique depuis le niveau gratuit d'abord.

Étape 2 : collecter les liens de propriétés depuis la page de recherche

Une page de recherche Zillow est une grille de cartes de propriétés, chacune pointant vers une annonce complète. Chargez le HTML rendu dans BeautifulSoup et extrayez le href du lien de chaque carte. Zillow imbrique ceux-ci dans sa grille de résultats, le sélecteur parcourt donc le conteneur de grille jusqu'au lien de la carte de propriété.

python
from bs4 import BeautifulSoup

CARD_SELECTOR = (
    'div[id="grid-search-results"] > ul > li[class^="ListItem-"] '
    'article[data-test="property-card"] a[data-test="property-card-link"]'
)

def get_property_urls(html):
    soup = BeautifulSoup(html, "html.parser")
    return [a["href"] for a in soup.select(CARD_SELECTOR) if a.get("href")]

Le sélecteur class^="ListItem-" est un sélecteur de préfixe : Zillow ajoute un hash à ses noms de classes générés, donc ListItem- correspond à chaque élément de liste quel que soit le suffixe. Exécuter ceci sur le HTML de recherche rendu retourne une liste propre d'URLs de pages de propriétés :

json
[
  "https://www.zillow.com/homedetails/1429-Girard-St-NW-101-Washington-DC-20009/2053968963_zpid/",
  "https://www.zillow.com/homedetails/1439-Euclid-St-NW-APT-301-Washington-DC-20009/68081615_zpid/",
  "https://www.zillow.com/homedetails/1362-Newton-St-NW-Washington-DC-20010/472850_zpid/",
  "https://www.zillow.com/homedetails/1458-Columbia-Rd-NW-APT-300-Washington-DC-20009/82293130_zpid/"
]
Les sélecteurs évoluent

Les noms de classes générés et les attributs data-test de Zillow changent sans préavis. Traitez les sélecteurs ici comme un modèle de départ, pas comme un contrat. Lorsqu'une liste revient vide, inspectez à nouveau la page en direct dans les outils de développement de votre navigateur et mettez à jour le sélecteur. La maintenance périodique des sélecteurs est normale pour tout scraper en production, ce n'est pas le signe que quelque chose est cassé.

Étape 3 : gérer la pagination entre les pages de recherche

Une page de recherche est une tranche du jeu de résultats. Zillow pagine avec un segment de chemin {pageNo}_p, vous récupérez donc la première page pour lire le nombre total de pages, puis parcourez chaque page en collectant les liens. Un petit gestionnaire de tentatives autour de la récupération évite qu'une page lente ne mette fin à l'exécution.

python
import time

def fetch_html(page_url, max_retries=2):
    for attempt in range(max_retries + 1):
        html = crawl(page_url)
        if html:
            return html
        if attempt < max_retries:
            print(f"Retrying ({attempt + 1}/{max_retries})...")
            time.sleep(1)
    print(f"Unable to fetch {page_url}")
    return None

def collect_all_urls(base_url, max_pages):
    first_html = fetch_html(f"{base_url}1_p/")
    if not first_html:
        return []

    soup = BeautifulSoup(first_html, "html.parser")
    last = soup.select_one("div.search-pagination > nav > li:nth-last-child(3)")
    total_pages = int(last.text) if last else 1
    pages = min(total_pages, max_pages)

    all_urls = get_property_urls(first_html)
    for page in range(2, pages + 1):
        html = fetch_html(f"{base_url}{page}_p/")
        if html:
            all_urls.extend(get_property_urls(html))
        time.sleep(2)
    return all_urls

fetch_html retente une récupération échouée jusqu'à deux fois avec une courte pause, renvoyant le HTML en cas de succès et None une fois qu'elle abandonne. collect_all_urls lit le numéro de page le plus élevé depuis la navigation de pagination (Zillow le place vers la fin de la liste, d'où le nth-last-child(3)), plafonne le crawl à votre limite max_pages pour qu'un grand marché ne parte pas à la dérive, et collecte les liens de chaque page. Le time.sleep(2) entre les pages rythme l'exécution pour ne pas surcharger le site.

Étape 4 : analyser chaque page de propriété

Avec une liste complète d'URLs de propriétés, récupérez chaque annonce et extrayez les champs. Zillow regroupe les détails principaux dans son bloc macro-data-view, les sélecteurs ci-dessous mappent donc prix, chambres, salles de bain, surface, adresse et type vers des éléments individuels. Chaque recherche est protégée pour qu'un champ manquant renvoie None au lieu de faire planter l'exécution.

python
VIEW = 'div[data-testid="macro-data-view"]'
FACTS = (
    f'{VIEW} > div[data-renderstrat="inline"]:nth-child(2) '
    'div[data-testid="bed-bath-sqft-facts"]'
)

def text_of(soup, selector):
    el = soup.select_one(selector)
    return el.get_text(strip=True) if el else None

def scrape_property(html, url):
    soup = BeautifulSoup(html, "html.parser")
    return {
        "link": url,
        "price": text_of(soup, f'{VIEW} span[data-testid="price"] > span'),
        "address": text_of(soup, f'{VIEW} div[class^="styles__AddressWrapper-"] > h1'),
        "beds": text_of(soup, f'{FACTS} > div[data-testid="bed-bath-sqft-fact-container"]:first-child > span:first-child'),
        "baths": text_of(soup, f'{FACTS} > button > div[data-testid="bed-bath-sqft-fact-container"] > span:first-child'),
        "size": text_of(soup, f'{FACTS} > div[data-testid="bed-bath-sqft-fact-container"]:last-child > span:first-child'),
        "type": text_of(soup, f'{VIEW} > div[data-renderstrat="inline"]:nth-child(3) div.dBmBNo:first-child > span'),
    }

L'assistant text_of interroge un élément et retourne son texte nettoyé, ou None si l'élément est absent, afin qu'une annonce omettant un champ ne brise pas la boucle. Les sélecteurs proviennent directement de la mise en page des annonces Zillow : price lit la balise de prix principal, address lit le H1 dans l'encapsuleur d'adresse, et les chambres, salles de bain et surface se trouvent tous dans le conteneur partagé bed-bath-sqft-facts, distingués par leur position. Les salles de bain sont dans un button dans le balisage de Zillow, c'est pourquoi ce sélecteur diffère légèrement des deux autres.

Étape 5 : assembler le script complet

Reliez maintenant les éléments en un script exécutable unique : collectez les URLs sur plusieurs pages, extrayez chaque propriété et exportez les enregistrements en JSON et CSV.

python
import csv
import json
import time
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

OPTIONS = {
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/122.0",
    "ajax_wait": "true",
    "page_wait": 5000,
}

CARD_SELECTOR = (
    'div[id="grid-search-results"] > ul > li[class^="ListItem-"] '
    'article[data-test="property-card"] a[data-test="property-card-link"]'
)
VIEW = 'div[data-testid="macro-data-view"]'
FACTS = (
    f'{VIEW} > div[data-renderstrat="inline"]:nth-child(2) '
    'div[data-testid="bed-bath-sqft-facts"]'
)

def crawl(page_url):
    response = api.get(page_url, OPTIONS)
    if response["headers"]["cb_status"] == "200":
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['headers']['cb_status']}")
    return None

def fetch_html(page_url, max_retries=2):
    for attempt in range(max_retries + 1):
        html = crawl(page_url)
        if html:
            return html
        if attempt < max_retries:
            time.sleep(1)
    return None

def text_of(soup, selector):
    el = soup.select_one(selector)
    return el.get_text(strip=True) if el else None

def get_property_urls(html):
    soup = BeautifulSoup(html, "html.parser")
    return [a["href"] for a in soup.select(CARD_SELECTOR) if a.get("href")]

def collect_all_urls(base_url, max_pages):
    first_html = fetch_html(f"{base_url}1_p/")
    if not first_html:
        return []
    soup = BeautifulSoup(first_html, "html.parser")
    last = soup.select_one("div.search-pagination > nav > li:nth-last-child(3)")
    total_pages = int(last.text) if last else 1
    pages = min(total_pages, max_pages)
    all_urls = get_property_urls(first_html)
    for page in range(2, pages + 1):
        html = fetch_html(f"{base_url}{page}_p/")
        if html:
            all_urls.extend(get_property_urls(html))
        time.sleep(2)
    return all_urls

def scrape_property(html, url):
    soup = BeautifulSoup(html, "html.parser")
    return {
        "link": url,
        "price": text_of(soup, f'{VIEW} span[data-testid="price"] > span'),
        "address": text_of(soup, f'{VIEW} div[class^="styles__AddressWrapper-"] > h1'),
        "beds": text_of(soup, f'{FACTS} > div[data-testid="bed-bath-sqft-fact-container"]:first-child > span:first-child'),
        "baths": text_of(soup, f'{FACTS} > button > div[data-testid="bed-bath-sqft-fact-container"] > span:first-child'),
        "size": text_of(soup, f'{FACTS} > div[data-testid="bed-bath-sqft-fact-container"]:last-child > span:first-child'),
        "type": text_of(soup, f'{VIEW} > div[data-renderstrat="inline"]:nth-child(3) div.dBmBNo:first-child > span'),
    }

def save_outputs(records):
    with open("zillow_properties.json", "w") as f:
        json.dump(records, f, indent=2)
    if not records:
        return
    with open("zillow_properties.csv", "w", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=records[0].keys())
        writer.writeheader()
        writer.writerows(records)

def main():
    serp_url = "https://www.zillow.com/columbia-heights-washington-dc/sale/"
    urls = collect_all_urls(serp_url, max_pages=2)

    records = []
    for url in urls:
        html = fetch_html(url)
        if html:
            records.append(scrape_property(html, url))
        time.sleep(2)

    save_outputs(records)
    print(f"Saved {len(records)} properties")

if __name__ == "__main__":
    main()

Le script collecte les liens de propriétés sur jusqu'à deux pages de recherche, récupère chaque annonce avec le gestionnaire de tentatives, l'analyse en un enregistrement et cadence la boucle avec une pause de deux secondes. save_outputs écrit à la fois un fichier JSON et un CSV en utilisant les clés du premier enregistrement comme en-tête, pour que vous ayez les données dans la forme que votre outil aval préfère. Ajustez max_pages et l'URL de recherche selon votre emplacement cible.

À quoi ressemble le résultat

Exécutez le script complet avec python zillow_scraper.py et vous obtenez un enregistrement structuré propre par propriété, prêt pour l'analyse, une base de données ou un tableur.

json
[
  {
    "link": "https://www.zillow.com/homedetails/1008-Fairmont-St-NW-Washington-DC-20001/473889_zpid/",
    "price": "$850,000",
    "address": "1008 Fairmont St NW, Washington, DC 20001",
    "beds": "3",
    "baths": "4",
    "size": "1,801",
    "type": "Townhouse"
  },
  {
    "link": "https://www.zillow.com/homedetails/1438-Meridian-Pl-NW-APT-106-Washington-DC-20010/467942_zpid/",
    "price": "$385,000",
    "address": "1438 Meridian Pl NW APT 106, Washington, DC 20010",
    "beds": "2",
    "baths": "2",
    "size": "634",
    "type": "Condominium"
  }
]

Le CSV correspondant porte les mêmes colonnes, une ligne par propriété, ce qui s'importe directement dans pandas ou n'importe quel tableur pour filtrer par tranche de prix, nombre de chambres ou type de bien.

Rester non bloqué à grande échelle

Même avec le rendu pris en charge, Zillow surveille le trafic à l'allure d'un scraper. Quelques bonnes habitudes gardent une exécution longue en bonne santé, et elles s'appliquent à n'importe quelle cible commerciale difficile.

  • Cadencez vos requêtes. Bombarder les annonces dans une boucle serrée est le moyen le plus rapide d'être limité ou soumis à un défi. Les pauses de deux secondes ci-dessus sont le plancher, pas le plafond ; élargissez-les pour les gros travaux et variez vos cibles plutôt que de crawler un seul chemin à pleine vitesse.
  • Appuyez-vous sur la rotation. Un pool d'IPs résidentielles distribue les requêtes sur de nombreuses adresses d'utilisateurs réels pour qu'aucune ne déclenche une limite de débit. La Crawling API gère cela pour vous ; si vous construisez votre propre pile, c'est la partie à bien réussir.
  • Lisez les codes de statut. Une exécution qui commence à renvoyer des valeurs cb_status non-200 vous indique que le débit actuel ou le niveau d'IP n'est plus suffisant. Traitez cela comme un signal pour ralentir, pas comme du bruit à ignorer.

Pour les crawls plus importants, le Crawler asynchrone met les requêtes en file d'attente et livre les résultats vers un webhook, ce qui convient à l'exécution de nombreuses pages de recherche sans maintenir des connexions ouvertes. Pour le guide général, voir comment extraire des données de sites web sans être bloqué. Et si vous souhaitez comparer les données de marché entre portails, la même approche s'applique à l'extraction de données Redfin, Realtor.com et Trulia.

Est-il légal d'extraire des données de Zillow ?

L'autorisation de scraper Zillow dépend des conditions d'utilisation de Zillow, de votre juridiction et de l'usage que vous faites des données. Les conditions de Zillow restreignent l'accès automatisé et la collecte de données, le scraping peut donc aller à l'encontre de ces conditions quel que soit le soin apporté à votre outillage. Zillow a également historiquement eu recours à des actions en justice concernant le scraping, ayant poursuivi des parties qui récoltaient ses annonces à grande échelle, il ne s'agit donc pas d'un risque hypothétique. Aucun code ici ne change quoi que ce soit à cela ; il ne fait que rendre la partie technique fonctionnelle. Lisez les Conditions d'utilisation de Zillow et son fichier robots.txt, et traitez les deux comme la limite de ce que vous collectez.

Quelques lignes à respecter. Collectez uniquement les données publiques d'annonces : le prix demandé, le nombre de chambres, de salles de bain, la surface, le type de bien et l'adresse postale que tout le monde peut voir sans compte. Évitez tout ce qui est lié à des personnes identifiables, y compris les coordonnées des agents, propriétaires ou autres personnes nommées sur une page, qui constituent des données personnelles et sortent du champ des annonces publiques. Respectez les attentes de débit de Zillow et maintenez votre volume de requêtes assez bas pour ne pas surcharger ses serveurs. Sachez également qu'une grande partie des données immobilières et de vente sous-jacentes sur les portails immobiliers provient de flux MLS, généralement sous licence avec leurs propres restrictions de redistribution, leur collecte ne vous donne donc pas le droit de les republier.

Ce guide est délibérément limité aux pages d'annonces publiques parce que c'est la ligne qui rend le travail défendable. Il ne couvre rien derrière une connexion, les données de recherche sauvegardée ou de compte, les coordonnées personnelles des individus, ni aucune tentative de contournement de l'authentification. Données d'annonces publiques uniquement. Si votre projet nécessite plus que cela, la bonne voie est un accord de licence : Zillow propose des API officielles et des programmes partenaires pour les cas d'utilisation autorisés, et les fournisseurs de données immobilières ou MLS agréés couvrent le reste. C'est la bonne approche pour un usage commercial ou en volume, pas un scraper plus ingénieux.

Récapitulatif

Points clés

  • Zillow est rendu côté client. Une simple requête renvoie une coquille avec seulement une partie des résultats, vous devez donc rendre la page avant de l'analyser.
  • Vous avez besoin du rendu et d'une IP de confiance ensemble. La Crawling API avec un token JS fait les deux en un seul appel ; ajax_wait et page_wait contrôlent la durée d'attente du contenu.
  • Travaillez en deux couches. Collectez les liens de propriétés de chaque page de recherche avec le sélecteur property-card-link, puis récupérez et analysez chaque annonce pour le prix, les chambres, les salles de bain, la surface, l'adresse et le type.
  • Pagineren et exporter. Parcourez les pages {pageNo}_p de Zillow jusqu'à un plafond, cadencez l'exécution avec de courtes pauses et écrivez les enregistrements en JSON et CSV.
  • Restez sur les données publiques. Respectez les CGU et le robots.txt de Zillow, notez qu'il a poursuivi en justice pour le scraping et que les données MLS sont souvent sous licence, et ne touchez jamais aux connexions, comptes ou coordonnées personnelles des individus.

Foire aux questions

Pourquoi une simple requête ne retourne-t-elle qu'une partie des résultats Zillow ?

Parce que Zillow charge ses résultats de recherche et les détails des annonces côté client avec JavaScript et Ajax. Le HTML initial est une coquille qui ne se remplit qu'après l'exécution des scripts de la page dans un navigateur, donc une requête HTTP brute renvoie le statut 200 avec la plupart des cartes et des champs d'annonces manquants. Pour obtenir le jeu complet, vous devez d'abord rendre la page, ce que gère le token JS de la Crawling API.

Ai-je besoin du token normal ou du token JS pour Zillow ?

Le token JS. Le token normal récupère le HTML statique, qui sur Zillow est la même coquille vide qu'une simple récupération renvoie. Le token JS rend la page dans un vrai navigateur avant de renvoyer le HTML, les cartes de recherche et les champs d'annonces sont donc présents quand BeautifulSoup les analyse.

Quelles données puis-je extraire d'une annonce Zillow ?

Les champs d'annonces publiques : le prix demandé, le nombre de chambres et de salles de bain, la surface, le type de bien, l'adresse postale et le lien de l'annonce. Restez sur les données visibles par tout visiteur sans compte, et évitez les coordonnées personnelles des agents ou propriétaires, qui sortent du champ des annonces publiques couvert par ce guide.

Mes sélecteurs retournent None. Qu'est-ce qui a changé ?

Presque certainement le balisage de Zillow. Ses noms de classes générés et attributs data-test (le préfixe ListItem-, le bloc macro-data-view, le conteneur bed-bath-sqft-facts) changent sans préavis, les sélecteurs qui fonctionnaient le mois dernier peuvent donc se casser. Inspectez à nouveau une page en direct dans les outils de développement de votre navigateur et mettez à jour les sélecteurs. La maintenance périodique des sélecteurs est normale pour tout scraper en production.

Comment gérer la pagination sur les annonces d'un emplacement ?

Zillow ajoute un segment {pageNo}_p au chemin de recherche. Récupérez la première page pour lire le nombre total de pages depuis la navigation de pagination, plafonnez le crawl à un max_pages, puis parcourez chaque page en collectant les liens de propriétés. La fonction collect_all_urls ci-dessus montre la boucle complète, avec une courte pause entre les pages.

Puis-je utiliser commercialement les données Zillow extraites ?

Considérez cela comme une question juridique, pas technique. Une grande partie des données immobilières de Zillow provient de flux MLS sous licence avec leurs propres conditions de redistribution, et les Conditions d'utilisation de Zillow restreignent la réutilisation, donc l'usage commercial ou en volume nécessite généralement une autorisation. Examinez les conditions, envisagez l'API officielle ou le programme partenaire de Zillow, et consultez un conseiller juridique avant de créer un produit basé sur ces données.

Commencer à construire

Crawlez n'importe quel site à grande échelle, sans combattre l'infrastructure.

Crawlbase gère les proxies, les empreintes et les CAPTCHA afin que votre équipe livre des pipelines de données au lieu de maintenir la plomberie de crawl. 1 000 requêtes gratuites, sans carte requise.

En libre-service · Sans appel commercial requis · Volumes de crawl entreprise disponibles