Récupérer les données des annonces Airbnb avec Python

Commentaires: 0

L'accès aux données d'Airbnb est essentiel pour analyser le marché de l'immobilier, étudier la dynamique des prix de location, mener des analyses concurrentielles et évaluer les avis et les évaluations. Il est possible d'y parvenir en récupérant des données sur le web. Cependant, l'accès à ces données peut s'avérer difficile car le scraping peut violer les conditions d'utilisation du site.

Ensuite, nous allons explorer un guide étape par étape sur la façon de développer un scraper web pour extraire des données des annonces Airbnb en utilisant Python et Selenium. Ce guide expliquera également comment éviter les blocages et les restrictions potentiels imposés par la plateforme.

Comprendre l'architecture du site web d'Airbnb

La première étape de la création d'un scraper web consiste à comprendre comment accéder aux pages web qui vous intéressent, car la structure des sites web peut souvent changer. Pour vous familiariser avec la structure d'un site, vous pouvez utiliser les outils de développement du navigateur pour inspecter le code HTML de la page web.

Pour accéder aux outils de développement, cliquez avec le bouton droit de la souris sur la page web et sélectionnez "Inspecter" ou utilisez le raccourci :

  • CTRL+SHIFT+I pour Windows;
  • Option + ⌘ + I sur Mac.

Chaque conteneur de liste est enveloppé dans un élément div avec l'attribut suivant : class="g1qv1ctd".

1.png

En cliquant sur "location" et en tapant "London, UK", nous pouvons accéder à la location proposée à Londres. Le site propose d'ajouter les dates d'arrivée et de départ. Cela permet de calculer le prix des chambres.

2.png

L'URL de cette page ressemblerait à ceci :

url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"

À partir de la page de recherche, nous allons récupérer les attributs suivants des données de la liste de produits :

  • Listing URL ;
  • Titre ;
  • Description ;
  • Cote ;
  • Prix ;
  • Informations complémentaires sur l'annonce (nombre de lits et dates disponibles).

3.png

Guide étape par étape sur la construction d'un programme de scraping Airbnb

Pour commencer le web scraping des données Airbnb, vous devez d'abord configurer votre environnement de développement. Voici les étapes à suivre:

Étape 1 : création d'un environnement virtuel

Les environnements virtuels vous permettent d'isoler les paquets Python et leurs dépendances pour différents projets. Cela permet d'éviter les conflits et de s'assurer que chaque projet dispose des bonnes dépendances.

Créer un environnement virtuel sous Windows

Ouvrez une invite de commande avec des privilèges d'administrateur et exécutez la commande suivante pour créer un nouvel environnement virtuel nommé "venv" :

python -m venv venv

Activer l'environnement virtuel :

venv\Scripts\activate

Création d'un environnement virtuel sur macOS/Linux

Ouvrez un terminal et exécutez la commande suivante pour créer un nouvel environnement virtuel nommé "venv" :

sudo python3 -m venv venv

Activer l'environnement virtuel :

source venv/bin/activate

Pour désactiver l'environnement virtuel, il suffit d'exécuter la commande suivante :

deactivate

Etape 2 : Installation des bibliothèques requises

Maintenant que vous avez mis en place un environnement virtuel, vous pouvez installer les bibliothèques nécessaires.

Comprendre les bibliothèques:

  • Selenium : Ce puissant outil de web scraping vous permet de contrôler par programme un navigateur web. Vous pouvez ainsi interagir avec les pages web, notamment en cliquant sur des boutons, en remplissant des formulaires et en naviguant dans les pages comme si vous étiez un véritable utilisateur.
  • Seleniumwire : Cette bibliothèque étend Selenium en vous permettant d'intercepter et d'inspecter les requêtes HTTP et d'intégrer des proxys à vos opérations de scraping. Ceci est très important car Selenium n'a pas de support proxy natif.
  • BeautifulSoup4 : Il s'agit d'une bibliothèque conçue pour analyser les fichiers HTML et XML. Elle vous aide à extraire des informations spécifiques des pages web de manière structurée et efficace.
  • lxml : Un analyseur HTML et XML rapide et robuste qui complète BeautifulSoup.

Dans votre environnement virtuel activé, exécutez la commande suivante pour installer les bibliothèques requises :

pip install selenium beautifulsoup4 lxml seleniumwire

Les pilotes de Sélénium

Selenium nécessite un pilote pour interfacer avec le navigateur choisi. Nous utiliserons Chrome pour ce guide. Cependant, assurez-vous d'avoir installé le pilote WebDriver approprié pour le navigateur de votre choix.

Une fois téléchargé, assurez-vous que le pilote est placé dans un répertoire accessible par la variable d'environnement PATH de votre système. Cela permettra à Selenium de trouver le pilote et de contrôler le navigateur.

Etape 3 : Importer des bibliothèques

Au début de votre fichier Python, importez les bibliothèques Seleniumwire et BeautifulSoup. Voici comment procéder :

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random

Nous importerons également les bibliothèques `random`, `time` et `csv` pour divers utilitaires.

Etape 4 : Intégration du mandataire

Ensuite, nous définissons une liste de proxys pour éviter qu'Airbnb ne les bloque. Si vous essayez d'envoyer une demande sans proxy premium, vous risquez d'obtenir une réponse "Accès refusé".

4.png

Vous pouvez configurer un proxy de la manière suivante :

# Liste des mandataires
proxies = [
     "username:password@Your_proxy_IP_Address:Your_proxy_port1",
     "username:password@Your_proxy_IP_Address:Your_proxy_port2",
     "username:password@Your_proxy_IP_Address:Your_proxy_port3",
     "username:password@Your_proxy_IP_Address:Your_proxy_port4",
     "username:password@Your_proxy_IP_Address:Your_proxy_port5",

]

Veillez à remplacer "Your_proxy_IP_Address" et "Your_proxy_port" par l'adresse proxy réelle que vous avez obtenue auprès du vendeur de proxy et remplacez également les valeurs de "username" et "password" par vos informations d'identification réelles.

Etape 5 : rotation des serveurs mandataires

La rotation des proxys est un aspect crucial du web scraping. Les sites web bloquent ou restreignent souvent l'accès aux bots et aux scrapers lorsqu'ils reçoivent plusieurs requêtes provenant de la même adresse IP. En passant par différentes adresses IP de proxy, vous pouvez éviter d'être détecté, apparaître comme plusieurs utilisateurs organiques et contourner la plupart des mesures anti-scraping mises en œuvre sur le site web.

Pour mettre en place la rotation des mandataires, il faut importer la bibliothèque "random". Nous définissons également une fonction `get_proxy()` pour sélectionner un proxy dans notre liste. Cette fonction sélectionne aléatoirement un proxy dans la liste des proxies en utilisant la méthode random.choice() et renvoie le proxy sélectionné.

def get_proxy():
    return random.choice(proxies)

Etape 6 : configuration de WebDriver

Ensuite, nous définissons la fonction principale appelée `listings()`. C'est ici que nous allons mettre en place notre "ChromeDriver". Cette fonction utilise Selenium pour naviguer sur la page d'annonces immobilières, attend que la page se charge, et analyse le HTML en utilisant Beautiful Soup.

def listings(url):

    proxy = get_proxy()
    proxy_options = {
        "proxy": {
            "http": f"http://{proxy}",
            "https": f"http://{proxy}",
            "no_proxy": "localhost,127.0.0.1",
        }
    }

    chrome_options = Options()
    chrome_options.add_argument("--headless")
  

    s = Service(
        "C:/Path_To_Your_WebDriver"
    )  # Remplacer par le chemin d'accès à ChromeDriver
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Ajuster en fonction du temps de chargement du site web

    soup = BeautifulSoup(driver.page_source, "lxml")

    driver.quit()

Ici, nous commençons par sélectionner un proxy aléatoire et par configurer les options du proxy. Ces options seront utilisées pour configurer le webdriver afin qu'il utilise le serveur proxy. Ensuite, nous configurons les options de Chrome. Ajoutez l'argument --headless pour exécuter le navigateur en mode headless, ce qui signifie que le navigateur fonctionnera en arrière-plan sans interface utilisateur graphique.

Initialiser ensuite le pilote web avec le service, les options seleniumwire et les options Chrome. Le webdriver est alors utilisé pour naviguer vers l'URL donnée. Nous ajoutons un temps de sommeil de 8 secondes pour permettre à la page de se charger complètement, puis nous analysons le code HTML retourné à l'aide de Beautiful Soup. Une fois l'analyse terminée, le webdriver est fermé.

Etape 7 : Recherche et extraction des données de référencement

Une fois que vous avez réussi à obtenir le contenu HTML, l'étape suivante est d'extraire les données pertinentes pour chaque listing. En utilisant BeautifulSoup, nous pouvons facilement naviguer dans la structure HTML et localiser les éléments contenant les informations de l'annonce.

Extraction des éléments de la liste

Tout d'abord, nous identifions tous les éléments de l'annonce sur la page. Ces éléments contiennent les données qui nous intéressent, telles que l'URL de l'annonce, le titre, la description, l'évaluation, le prix et les informations complémentaires.

listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:

Ce code utilise la méthode find_all() de BeautifulSoup pour localiser tous les éléments div avec la classe "g1qv1ctd". Ces éléments représentent des annonces individuelles sur la page Airbnb. Il parcourt ensuite chacun de ces éléments pour en extraire les données pertinentes.

Extraction de l'URL du listing

Pour chaque élément d'inscription trouvé, nous extrayons l'URL de l'inscription.

URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
    "https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)

Ici, nous recherchons dans notre objet "soupe" une balise d'ancrage de la classe "rfexzly". S'il trouve cet élément, il extrait l'attribut "href" (qui contient l'URL relative) et l'ajoute à l'URL de base pour créer l'URL complète de la liste. Si l'élément n'est pas trouvé, il attribue une chaîne vide pour éviter les erreurs.

Extraire le titre de l'annonce

Tout d'abord, nous allons extraire l'URL de chaque fiche. Cela nous permettra de visiter les pages individuelles des annonces plus tard, si nécessaire.

title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
    title_element.get_text(strip=True) if title_element else ""
)

Le titre est contenu dans un élément "div" de classe "t1jojoys". Nous récupérons le contenu textuel de cet élément, en supprimant tout espace blanc de début ou de fin. Une chaîne vide est stockée si l'élément n'est pas trouvé.

Extraire la description de l'annonce

Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
    Description_element.get_text(strip=True) if Description_element else ""
)

Comme pour l'extraction du titre, ce code trouve un élément span avec la classe "t6mzqp7". Nous extrayons et nettoyons ensuite le contenu textuel de cet élément, qui contient une brève description de l'annonce.

Extraction de l'évaluation de l'inscription

rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
    rating_element.get_text(strip=True) if rating_element else ""
)

Comme le montre le code ci-dessus, un élément span de classe "ru0q88m" contient la valeur de l'évaluation. Nous extrayons cette valeur en veillant à supprimer tout espace blanc inutile.

Extraire le prix d'inscription

Enfin, nous extrayons le prix de l'annonce.

price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
    f"{price_element.get_text(strip=True)} per night" if price_element else ""
)

Ce code localise l'élément de la classe "_1y74zjx" dans le listing_element actuel. Si cet élément, qui contient généralement les informations sur le prix, est trouvé, son contenu textuel est extrait, nettoyé et complété par "par nuit" pour former une chaîne de prix plus informative.

Extraction d'informations supplémentaires sur les listes

Certaines listes peuvent contenir des informations supplémentaires que nous pouvons extraire.

listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
listing_data["Additional Listing information"] = (
    listing_info_element.get_text(strip=True) if listing_info_element else ""
)

Nous recherchons un élément span avec l'attribut aria-hidden="true" pour trouver des informations supplémentaires sur l'annonce. Après avoir extrait toutes les données pertinentes de chaque élément de l'annonce, nous ajoutons les données collectées à une liste d'annonces.

listings.append(listing_data)

Une fois que toutes les inscriptions ont été traitées, nous renvoyons la liste des inscriptions, chacune étant représentée par un dictionnaire contenant les données extraites.

return listings

Etape 8 : écrire les données dans un fichier CSV

Après avoir réussi à récupérer les données des pages d'inscription d'Airbnb, l'étape suivante consiste à stocker ces informations précieuses pour les analyser et les consulter ultérieurement. Nous utilisons la bibliothèque csv pour cette tâche. Nous ouvrons un fichier CSV en mode écriture et créons un objet csv.DictWriter. Nous écrivons ensuite l'en-tête et les données dans le fichier.

airbnb_listings = listings(url)

csv_file_path = "proxy_web_listings_output.csv"

with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
    fieldnames = [
        "Listing URL",
        "Title",
        "Description",
        "Rating",
        "Price",
        "Additional Listing information",
    ]
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    writer.writeheader()
    for listing in airbnb_listings:
        writer.writerow(listing)

print(f"Data has been exported to {csv_file_path}")

Voici le code complet que nous avons utilisé pour ce tutoriel :

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random

# Liste des mandataires
proxies = [
 "username:password@Your_proxy_IP_Address:Your_proxy_port1",
 "username:password@Your_proxy_IP_Address:Your_proxy_port2",
 "username:password@Your_proxy_IP_Address:Your_proxy_port3",
 "username:password@Your_proxy_IP_Address:Your_proxy_port4",
 "username:password@Your_proxy_IP_Address:Your_proxy_port5",
]

def get_proxy():
    return random.choice(proxies)


def listings(url):

    proxy = get_proxy()
    proxy_options = {
        "proxy": {
            "http": f"http://{proxy}",
            "https": f"http://{proxy}",
            "no_proxy": "localhost,127.0.0.1",
        }
    }

    chrome_options = Options()
    chrome_options.add_argument("--headless")
  

    s = Service(
        "C:/Path_To_Your_WebDriver"
    )  # Remplacer par le chemin d'accès à ChromeDriver
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Ajuster en fonction du temps de chargement du site web

    soup = BeautifulSoup(driver.page_source, "lxml")

    driver.quit()

    listings = []

    # Trouver tous les éléments de la liste sur la page
    listing_elements = soup.find_all("div", class_="g1qv1ctd")

    for listing_element in listing_elements:
        # Extraire les données de chaque élément de la liste
        listing_data = {}

        # URL de l'inscription
        URL_element = soup.find("a", class_="rfexzly")
        listing_data["Listing URL"] = (
            "https://www.airbnb.com" + URL_element["href"] if URL_element else ""
        )

        # Titre
        title_element = listing_element.find("div", class_="t1jojoys")
        listing_data["Title"] = (
            title_element.get_text(strip=True) if title_element else ""
        )

        # Description
        Description_element = listing_element.find("span", class_="t6mzqp7")
        listing_data["Description"] = (
            Description_element.get_text(strip=True) if Description_element else ""
        )

        # Classement
        rating_element = listing_element.find("span", class_="ru0q88m")
        listing_data["Rating"] = (
            rating_element.get_text(strip=True) if rating_element else ""
        )

        # Prix
        price_element = listing_element.select_one("._1y74zjx")
        listing_data["Price"] = (
            f"{price_element.get_text(strip=True)} per night" if price_element else ""
        )

        # Informations complémentaires sur la liste
        listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
        listing_data["Additional Listing information"] = (
            listing_info_element.get_text(strip=True) if listing_info_element else ""
        )

        # Ajouter les données du listing à la liste
        listings.append(listing_data)

    return listings


url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"


airbnb_listings = listings(url)

csv_file_path = "proxy_web_listings_output.csv"

with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
    fieldnames = [
        "Listing URL",
        "Title",
        "Description",
        "Rating",
        "Price",
        "Additional Listing information",
    ]
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    writer.writeheader()
    for listing in airbnb_listings:
        writer.writerow(listing)

print(f"Data has been exported to {csv_file_path}")

Cette partie du code garantit que les données extraites sont stockées dans un fichier CSV nommé "proxy_web_listings_output.csv".

Résultats

Les résultats de notre scraper sont enregistrés dans un fichier CSV appelé "proxy_web_listings_output.csv", comme indiqué ci-dessous.

5.jpg

Ce guide explique efficacement comment extraire des données des annonces Airbnb à l'aide de Python, ce qui permet d'extraire des détails clés tels que les prix, la disponibilité et les avis. Il souligne l'importance d'utiliser des proxies et de les faire tourner pour éviter d'être bloqué par les mesures anti-bots d'Airbnb.

Commentaires:

0 Commentaires