Scraping dei dati degli annunci di Airbnb con Python

Commenti: 0

Ottenere l'accesso ai dati di Airbnb è fondamentale per analizzare il mercato immobiliare, ricercare le dinamiche dei prezzi degli affitti, condurre un'analisi della concorrenza e valutare le recensioni e le valutazioni. Questo può essere ottenuto attraverso lo scraping dei dati web. Tuttavia, l'accesso a questi dati può essere difficile, poiché lo scraping può violare i termini di utilizzo del sito.

A seguire, scopriremo una guida passo-passo su come sviluppare uno scraper web per estrarre dati dagli annunci di Airbnb utilizzando Python e Selenium. Questa guida spiegherà anche come evitare i potenziali blocchi e le restrizioni imposte dalla piattaforma.

Comprendere l'architettura del sito web di Airbnb

Il primo passo per creare un web scraper è capire come accedere alle pagine web di interesse, poiché la struttura dei siti web può spesso cambiare. Per familiarizzare con la struttura di un sito, è possibile utilizzare gli strumenti di sviluppo del browser per ispezionare l'HTML della pagina web.

Per accedere agli Strumenti per gli sviluppatori, fare clic con il pulsante destro del mouse sulla pagina web e selezionare "Ispeziona" o utilizzare la scorciatoia:

  • CTRL+SHIFT+I per Windows;
  • Option + ⌘ + I su Mac.

Ogni contenitore di annunci è racchiuso in un elemento div con il seguente attributo: class="g1qv1ctd".

1.png

Cliccando su "location" e digitando "London, UK" si accede alla posizione offerta a Londra. Il sito suggerisce di aggiungere le date di check-in e check-out. Questo permette di calcolare il prezzo delle camere.

2.png

L'URL di questa pagina dovrebbe essere simile a questo:

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"

Dalla pagina di ricerca, si scraperanno i seguenti attributi dei dati dell'elenco dei prodotti:

  • Listing URL;
  • Titolo;
  • Descrizione;
  • Valutazione;
  • Prezzo;
  • Informazioni aggiuntive sull'annuncio (numero di letti e date disponibili).

3.png

Guida passo passo alla creazione di un programma di scraping di Airbnb

Per iniziare il web scraping dei dati di Airbnb, è necessario impostare prima l'ambiente di sviluppo. Ecco i passaggi per farlo:

Passo 1: Creare un ambiente virtuale

Gli ambienti virtuali consentono di isolare i pacchetti Python e le loro dipendenze per i diversi progetti. Questo aiuta a prevenire i conflitti e garantisce che ogni progetto abbia le dipendenze corrette installate.

Creazione di un ambiente virtuale su Windows

Aprire un prompt dei comandi con privilegi di amministratore ed eseguire il seguente comando per creare un nuovo ambiente virtuale denominato "venv":

python -m venv venv

Attivare l'ambiente virtuale:

venv\Scripts\activate

Creazione di un ambiente virtuale su macOS/Linux

Aprite un terminale ed eseguite il seguente comando per creare un nuovo ambiente virtuale denominato "venv":

sudo python3 -m venv venv

Attivare l'ambiente virtuale:

source venv/bin/activate

Per disattivare l'ambiente virtuale, basta eseguire il seguente comando:

deactivate

Passo 2: Installazione delle librerie necessarie

Ora che è stato creato un ambiente virtuale, è possibile installare le librerie necessarie.

Comprendere le librerie:

  • Selenium: Questo potente strumento di web scraping consente di controllare programmaticamente un browser web. In questo modo è possibile interagire con le pagine web, facendo clic su pulsanti, compilando moduli e navigando tra le pagine come se si fosse un utente reale.
  • Seleniumwire: Questa libreria estende Selenium consentendo di intercettare e ispezionare le richieste HTTP e di integrare i proxy nelle operazioni di scraping. Questo è molto importante perché Selenium non ha un supporto proxy nativo.
  • BeautifulSoup4: è una libreria progettata per l'analisi di file HTML e XML. Aiuta a estrarre informazioni specifiche dalle pagine web in modo strutturato ed efficiente.
  • lxml: Un parser HTML e XML veloce e robusto, complementare a BeautifulSoup.

Nell'ambiente virtuale attivato, eseguire il seguente comando per installare le librerie necessarie:

pip install selenium beautifulsoup4 lxml seleniumwire

Driver Selenium

Selenium richiede un driver per interfacciarsi con il browser scelto. In questa guida utilizzeremo Chrome. Tuttavia, assicurarsi di aver installato il WebDriver appropriato per il browser scelto.

Una volta scaricato, assicurarsi che il driver sia collocato in una directory accessibile dalla variabile d'ambiente PATH del sistema. Ciò consentirà a Selenium di trovare il driver e di controllare il browser.

Passo 3: Importare le librerie

All'inizio del file Python, importare le librerie Seleniumwire e BeautifulSoup. Ecco come fare:

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

Importeremo anche le librerie `random', `time' e `csv' per varie utilità.

Passo 4: Integrazione del proxy

Quindi, definiamo un elenco di proxy per evitare di essere bloccati da Airbnb. Quando si tenta di inviare una richiesta senza un proxy premium, è possibile che venga visualizzata la risposta "Accesso negato".

4.png

È possibile impostare un proxy come segue:

# List of proxies
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",

]

Assicuratevi di sostituire "Your_proxy_IP_Address" e "Your_proxy_port" con l'indirizzo proxy effettivo ottenuto da Proxy-seller e sostituite anche i valori di "username" e "password" con le vostre credenziali effettive.

Passo 5: Rotazione dei proxy

La rotazione dei proxy è un aspetto cruciale del web scraping. I siti web spesso bloccano o limitano l'accesso a bot e scrapers quando ricevono più richieste dallo stesso indirizzo IP. Ruotando attraverso diversi indirizzi IP proxy, è possibile evitare il rilevamento, apparire come più utenti organici e aggirare la maggior parte delle misure anti-scraping implementate sul sito web.

Per impostare la rotazione dei proxy, importare la libreria "random". Definiamo anche una funzione `get_proxy()` per selezionare un proxy dal nostro elenco. Questa funzione seleziona casualmente un proxy dall'elenco dei proxy utilizzando il metodo random.choice() e restituisce il proxy selezionato.

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

Passo 6: Configurare WebDriver

Successivamente, definiamo la funzione principale chiamata `listings()`. È qui che imposteremo il nostro "ChromeDriver". Questa funzione utilizza Selenium per navigare nella pagina degli annunci immobiliari, attende il caricamento della pagina e analizza l'HTML utilizzando 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"
    )  # Sostituire con il percorso di ChromeDriver
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Regolare in base al tempo di caricamento del sito web

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

    driver.quit()

Si inizia selezionando un proxy casuale e impostando le opzioni del proxy. Queste opzioni saranno utilizzate per configurare il webdriver in modo che utilizzi il server proxy. Successivamente, si impostano le opzioni di Chrome. Aggiungere l'argomento --headless per eseguire il browser in modalità headless, il che significa che il browser verrà eseguito in background senza interfaccia grafica.

Quindi inizializzare il webdriver con il servizio, le opzioni di seleniumwire e le opzioni di Chrome. Il webdriver viene quindi utilizzato per navigare verso l'URL indicato. Aggiungiamo un tempo di sospensione di 8 secondi per consentire il caricamento completo della pagina e poi analizziamo l'HTML restituito usando Beautiful Soup. Al termine dell'analisi, si chiude il webdriver.

Passo 7: trovare ed estrarre i dati dell'elenco

Una volta ottenuto il contenuto HTML, il passo successivo è quello di estrarre i dati rilevanti per ogni annuncio. Utilizzando BeautifulSoup, possiamo navigare facilmente nella struttura HTML e individuare gli elementi che contengono le informazioni sull'annuncio.

Estrazione degli elementi dell'elenco

Innanzitutto, identifichiamo tutti gli elementi dell'inserzione presenti nella pagina. Questi elementi contengono i dati che ci interessano, come l'URL dell'annuncio, il titolo, la descrizione, la valutazione, il prezzo e altre informazioni.

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

Questo codice utilizza il metodo find_all() di BeautifulSoup per individuare tutti gli elementi div con la classe "g1qv1ctd". Questi elementi rappresentano i singoli annunci sulla pagina di Airbnb. Quindi esegue un ciclo su ciascuno di questi elementi per estrarre i dati rilevanti.

Estrazione dell'URL dell'elenco

Per ogni elemento dell'inserzione trovato, estraiamo l'URL dell'inserzione.

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

In questo caso, cerchiamo all'interno del nostro oggetto "soup" un tag di ancoraggio con la classe "rfexzly". Se trova questo elemento, estrae l'attributo "href" (che contiene l'URL relativo) e lo aggiunge all'URL di base per creare l'URL completo dell'elenco. Se l'elemento non viene trovato, assegna una stringa vuota per evitare errori.

Estrazione del titolo dell'inserzione

Per prima cosa, estrarremo l'URL di ciascun annuncio. Questo ci permetterà di visitare le pagine dei singoli annunci in un secondo momento, se necessario.

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

Il titolo è contenuto in un elemento "div" con la classe "t1jojoys". Si recupera il contenuto del testo di questo elemento, eliminando tutti gli spazi bianchi iniziali o finali. Se l'elemento non viene trovato, viene memorizzata una stringa vuota.

Estrazione della descrizione dell'annuncio

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

Analogamente all'estrazione del titolo, questo codice trova un elemento span con la classe "t6mzqp7". Quindi estraiamo e puliamo il contenuto testuale di questo elemento, che contiene una breve descrizione dell'annuncio.

Estrazione della valutazione dell'inserzione

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

Come si vede nel codice qui sopra, un elemento span con la classe "ru0q88m" contiene il valore della valutazione. Estraiamo questo valore, assicurandoci di eliminare tutti gli spazi bianchi non necessari.

Estrazione del prezzo di quotazione

Infine, estraiamo il prezzo dell'inserzione.

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

Questo codice individua l'elemento con la classe "_1y74zjx" all'interno dell'elemento_inserzione corrente. Se questo elemento, che di solito contiene le informazioni sul prezzo, viene trovato, il suo contenuto testuale viene estratto, pulito e aggiunto a "per night" per formare una stringa di prezzo più informativa.

Estrazione di informazioni aggiuntive sull'inserzione

Alcuni annunci possono contenere informazioni aggiuntive che possiamo estrarre.

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

Cerchiamo un elemento span con l'attributo aria-hidden="true" per trovare qualsiasi informazione aggiuntiva sull'annuncio. Dopo aver estratto tutti i dati rilevanti da ciascun elemento dell'inserzione, aggiungiamo i dati raccolti a un elenco di inserzioni.

listings.append(listing_data)

Una volta che tutti gli elenchi sono stati elaborati, viene restituito l'elenco degli elenchi, ciascuno rappresentato come un dizionario contenente i dati estratti.

return listings

Passo 8: scrittura dei dati in un file CSV

Dopo aver effettuato con successo lo scraping dei dati dalle pagine degli annunci di Airbnb, il passo successivo è la memorizzazione di queste preziose informazioni per analisi e riferimenti futuri. Per questo compito utilizziamo la libreria csv. Apriamo un file CSV in modalità di scrittura e creiamo un oggetto csv.DictWriter. Quindi scriviamo l'intestazione e i dati nel file.

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

Ecco il codice completo che abbiamo utilizzato per questa esercitazione:

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

# Elenco dei proxy
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"
    )  # Sostituire con il percorso di ChromeDriver
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Regolare in base al tempo di caricamento del sito web

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

    driver.quit()

    listings = []

    # Trova tutti gli elementi dell'elenco nella pagina
    listing_elements = soup.find_all("div", class_="g1qv1ctd")

    for listing_element in listing_elements:
        # Estrarre i dati da ogni elemento dell'elenco
        listing_data = {}

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

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

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

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

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

        # Informazioni aggiuntive sull'inserzione
        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 ""
        )

        # Aggiungere i dati dell'elenco all'elenco
        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}")

Questa parte del codice assicura che i dati raschiati siano memorizzati in un file CSV denominato "proxy_web_listings_output.csv".

Risultati

I risultati del nostro scraper vengono salvati in un file CSV chiamato "proxy_web_listings_output.csv", come si vede di seguito.

5.jpg

Questa guida spiega efficacemente come raschiare i dati dagli annunci di Airbnb utilizzando Python, consentendo di estrarre dettagli chiave come prezzi, disponibilità e recensioni. Sottolinea l'importanza di utilizzare i proxy e di ruotarli per evitare di essere bloccati dalle misure anti-bot di Airbnb.

Commenti:

0 Commenti