Skrobanie danych ofert Airbnb za pomocą Pythona

Komentarze: 0

Uzyskanie dostępu do danych z Airbnb jest kluczowe dla analizy rynku nieruchomości, badania dynamiki cen wynajmu, przeprowadzania analiz konkurencyjnych oraz oceny recenzji i ocen. Można to osiągnąć poprzez zbieranie danych z sieci (web scraping). Jednak dostęp do tych danych może być wyzwaniem, ponieważ zbieranie danych może naruszać warunki korzystania z serwisu.

Następnie omówimy krok po kroku, jak opracować program do zbierania danych z ofert Airbnb przy użyciu Python i Selenium. Przewodnik ten obejmie również, jak unikać potencjalnych blokad i ograniczeń narzucanych przez platformę.

Rozumienie architektury strony internetowej Airbnb

Pierwszym krokiem w tworzeniu programu do zbierania danych jest zrozumienie, jak uzyskać dostęp do stron internetowych, które nas interesują, ponieważ struktura stron internetowych może się często zmieniać. Aby zapoznać się ze strukturą strony, można skorzystać z narzędzi deweloperskich przeglądarki, aby sprawdzić HTML strony internetowej.

Aby uzyskać dostęp do narzędzi deweloperskich, kliknij prawym przyciskiem myszy na stronie internetowej i wybierz "Zbadaj" lub użyj skrótu:

  • CTRL+SHIFT+I dla Windows;
  • Option + ⌘ + I na Mac.

Każdy kontener oferty jest opakowany w element div z następującym atrybutem: class="g1qv1ctd".

1.png

Klikając na "lokalizację" i wpisując "Londyn, UK", możemy uzyskać dostęp do ofert w Londynie. Strona sugeruje dodanie dat zameldowania i wymeldowania, co pozwala na obliczenie ceny pokoi.

2.png

URL tej strony będzie wyglądać mniej więcej tak:

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"

Na stronie wyników wyszukiwania będziemy zbierać następujące atrybuty danych z ofert:

  • URL oferty;
  • Tytuł;
  • Opis;
  • Ocena;
  • Cena;
  • Dodatkowe informacje o ofercie (liczba łóżek i dostępne daty).

3.png

Przewodnik krok po kroku dotyczący tworzenia programu do zbierania danych z Airbnb

Aby rozpocząć zbieranie danych z Airbnb, najpierw należy skonfigurować środowisko programistyczne. Oto kroki, jak to zrobić:

Krok 1: Tworzenie środowiska wirtualnego

Środowiska wirtualne pozwalają na izolowanie pakietów Python i ich zależności dla różnych projektów. Pomaga to zapobiec konfliktom i zapewnia, że każdy projekt ma zainstalowane odpowiednie zależności.

Tworzenie środowiska wirtualnego w Windows

Otwórz wiersz polecenia z uprawnieniami administratora i uruchom następujące polecenie, aby utworzyć nowe środowisko wirtualne o nazwie “venv”:

python -m venv venv

Aktywuj środowisko wirtualne:

venv\Scripts\activate

Tworzenie środowiska wirtualnego w systemie macOS/Linux

Otwórz terminal i uruchom następujące polecenie, aby utworzyć nowe środowisko wirtualne o nazwie "venv":

sudo python3 -m venv venv

Aktywacja środowiska wirtualnego:

source venv/bin/activate

Aby dezaktywować środowisko wirtualne, wystarczy uruchomić następujące polecenie:

deactivate

Krok 2: Instalacja wymaganych bibliotek

Po skonfigurowaniu środowiska wirtualnego można zainstalować niezbędne biblioteki.

Zrozumienie bibliotek:

  • Selenium: To potężne narzędzie do skrobania stron internetowych pozwala programowo kontrolować przeglądarkę internetową. Pozwala to na interakcję ze stronami internetowymi, w tym klikanie przycisków, wypełnianie formularzy i nawigowanie po stronach tak, jakbyś był prawdziwym użytkownikiem.
  • Seleniumwire: Ta biblioteka rozszerza Selenium, umożliwiając przechwytywanie i inspekcję żądań HTTP oraz integrację serwerów proxy z operacjami skrobania. Jest to bardzo ważne, ponieważ Selenium nie posiada natywnej obsługi proxy.
  • BeautifulSoup4: Jest to biblioteka przeznaczona do analizowania plików HTML i XML. Pomaga wyodrębnić określone informacje ze stron internetowych w uporządkowany i wydajny sposób.
  • lxml: Szybki i solidny parser HTML i XML, który uzupełnia BeautifulSoup.

W aktywowanym środowisku wirtualnym uruchom następujące polecenie, aby zainstalować wymagane biblioteki:

pip install selenium beautifulsoup4 lxml seleniumwire

Sterowniki Selenium

Selenium wymaga sterownika do połączenia z wybraną przeglądarką. W tym przewodniku użyjemy przeglądarki Chrome. Upewnij się jednak, że zainstalowałeś odpowiedni WebDriver dla wybranej przeglądarki.

Po pobraniu upewnij się, że sterownik jest umieszczony w katalogu dostępnym przez zmienną środowiskową PATH systemu. Pozwoli to Selenium znaleźć sterownik i kontrolować przeglądarkę.

Krok 3: Import bibliotek

Na początku pliku Pythona zaimportuj biblioteki Seleniumwire i BeautifulSoup. Można to zrobić w następujący sposób:

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

Zaimportujemy również biblioteki `random`, `time` i `csv` dla różnych narzędzi.

Krok 4: Integracja proxy

Następnie definiujemy listę serwerów proxy, aby uniknąć zablokowania przez Airbnb. Podczas próby wysłania żądania bez proxy premium, możesz napotkać odpowiedź "Odmowa dostępu".

4.png

Serwer proxy można skonfigurować w następujący sposób:

# Lista pełnomocników
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",

]

Upewnij się, że zastąpiłeś "Your_proxy_IP_Address" i "Your_proxy_port" rzeczywistym adresem proxy uzyskanym od sprzedawcy proxy, a także zastąpiłeś wartości "username" i "password" swoimi rzeczywistymi poświadczeniami.

Krok 5: Obracanie serwerów proxy

Rotacja serwerów proxy jest kluczowym aspektem web scrapingu. Strony internetowe często blokują lub ograniczają dostęp botom i scraperom, gdy otrzymują wiele żądań z tego samego adresu IP. Obracając różnymi adresami IP proxy, można uniknąć wykrycia, pojawić się jako wielu organicznych użytkowników i ominąć większość środków zapobiegających skrobaniu zaimplementowanych na stronie internetowej.

Aby ustawić rotację proxy, zaimportuj bibliotekę "random". Definiujemy również funkcję `get_proxy()`, aby wybrać proxy z naszej listy. Funkcja ta losowo wybiera proxy z listy proxy przy użyciu metody random.choice() i zwraca wybrane proxy.

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

Krok 6: Konfiguracja WebDriver

Następnie definiujemy główną funkcję o nazwie `listings()`. To tutaj skonfigurujemy nasz "ChromeDriver". Ta funkcja używa Selenium do nawigacji po stronie z listą nieruchomości, czeka na załadowanie strony i analizuje HTML za pomocą 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"
    )  # Zastąp ścieżką do ChromeDriver
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Dostosuj na podstawie czasu ładowania strony

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

    driver.quit()

Tutaj zaczynamy od wybrania losowego serwera proxy i skonfigurowania opcji proxy. Opcje te zostaną wykorzystane do skonfigurowania webdrivera do korzystania z serwera proxy. Następnie ustawiamy opcje Chrome. Dodajemy argument --headless, aby uruchomić przeglądarkę w trybie headless, co oznacza, że przeglądarka będzie działać w tle bez graficznego interfejsu użytkownika.

Następnie należy zainicjować webdriver z usługą, opcjami seleniumwire i opcjami Chrome. Webdriver jest następnie używany do nawigacji do podanego adresu URL. Dodajemy czas uśpienia wynoszący 8 sekund, aby umożliwić całkowite załadowanie strony, a następnie analizujemy zwrócony kod HTML za pomocą Beautiful Soup. Po zakończeniu parsowania zamykamy webdriver.

Krok 7: Wyszukiwanie i wyodrębnianie danych aukcji

Po pomyślnym uzyskaniu zawartości HTML, następnym krokiem jest wyodrębnienie odpowiednich danych dla każdej oferty. Korzystając z BeautifulSoup, możemy łatwo poruszać się po strukturze HTML i zlokalizować elementy zawierające informacje o ofercie.

Wyodrębnianie elementów listy

Najpierw identyfikujemy wszystkie elementy oferty na stronie. Elementy te zawierają interesujące nas dane, takie jak adres URL oferty, tytuł, opis, ocena, cena i dodatkowe informacje.

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

Ten kod wykorzystuje metodę find_all() BeautifulSoup do zlokalizowania wszystkich elementów div z klasą "g1qv1ctd". Elementy te reprezentują poszczególne oferty na stronie Airbnb. Następnie przechodzi przez każdy z tych elementów, aby wyodrębnić odpowiednie dane.

Wyodrębnianie adresu URL listy

Dla każdego znalezionego elementu oferty wyodrębniamy adres URL oferty.

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

Tutaj szukamy w naszym obiekcie "soup" znacznika kotwicy z klasą "rfexzly". Jeśli znajdzie ten element, wyodrębnia atrybut "href" (który zawiera względny adres URL) i dołącza go do podstawowego adresu URL, aby utworzyć pełny adres URL listy. Jeśli element nie zostanie znaleziony, przypisuje pusty ciąg znaków, aby uniknąć błędów.

Wyodrębnianie tytułu aukcji

Najpierw wyodrębnimy adres URL dla każdej oferty. Pozwoli nam to później odwiedzić poszczególne strony ofert, jeśli zajdzie taka potrzeba.

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

Tytuł jest zawarty w elemencie "div" z klasą "t1jojoys". Pobieramy zawartość tekstową tego elementu, usuwając wszelkie początkowe i końcowe białe znaki. Jeśli element nie zostanie znaleziony, zapisywany jest pusty ciąg znaków.

Wyodrębnianie opisu aukcji

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

Podobnie jak w przypadku wyodrębniania tytułu, kod ten znajduje element span z klasą "t6mzqp7". Następnie wyodrębniamy i czyścimy zawartość tekstową tego elementu, która zawiera krótki opis oferty.

Wyciąganie oceny aukcji

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

Jak widać w powyższym kodzie, element span z klasą "ru0q88m" przechowuje wartość ratingu. Wyodrębniamy tę wartość, usuwając wszelkie niepotrzebne białe znaki.

Obliczanie ceny ofertowej

Na koniec wyodrębniamy cenę oferty.

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

Ten kod lokalizuje element z klasą "_1y74zjx" w bieżącym listing_element. Jeśli ten element, który zazwyczaj zawiera informacje o cenie, zostanie znaleziony, jego zawartość tekstowa zostanie wyodrębniona, wyczyszczona i dołączona do "za noc", aby utworzyć bardziej informacyjny ciąg ceny.

Wyodrębnianie dodatkowych informacji o aukcji

Niektóre oferty mogą zawierać dodatkowe informacje, które możemy wyodrębnić.

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

Szukamy elementu span z atrybutem aria-hidden="true", aby znaleźć wszelkie dodatkowe informacje na temat oferty. Po wyodrębnieniu wszystkich istotnych danych z każdego elementu oferty, dołączamy zebrane dane do listy ofert.

listings.append(listing_data)

Po przetworzeniu wszystkich ofert zwracamy listę ofert, z których każda jest reprezentowana jako słownik zawierający wyodrębnione dane.

return listings

Krok 8: Zapis danych do pliku CSV

Po pomyślnym zeskrobaniu danych ze stron z ofertami Airbnb, kolejnym ważnym krokiem jest przechowywanie tych cennych informacji do przyszłej analizy i odniesienia. Do tego zadania wykorzystujemy bibliotekę csv. Otwieramy plik CSV w trybie zapisu i tworzymy obiekt csv.DictWriter. Następnie zapisujemy nagłówek i dane do pliku.

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

Oto kompletny kod, którego użyliśmy w tym samouczku:

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

# Lista pełnomocników
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"
    )  # Zastąp ścieżką do ChromeDriver
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Dostosuj na podstawie czasu ładowania strony

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

    driver.quit()

    listings = []

    # Znajdź wszystkie elementy listy na stronie
    listing_elements = soup.find_all("div", class_="g1qv1ctd")

    for listing_element in listing_elements:
        # Wyodrębnij dane z każdego elementu listy
        listing_data = {}

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

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

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

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

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

        # Dodatkowe informacje o ofercie
        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 ""
        )

        # Dołącz dane listy do listy
        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}")

Ta część kodu zapewnia, że zeskrobane dane są przechowywane w pliku CSV o nazwie "proxy_web_listings_output.csv".

Wyniki

Wyniki naszego scrapera są zapisywane w pliku CSV o nazwie "proxy_web_listings_output.csv", jak pokazano poniżej.

5.jpg

Ten przewodnik skutecznie wyjaśnia, jak skrobać dane z ofert Airbnb za pomocą Pythona, umożliwiając wyodrębnienie kluczowych szczegółów, takich jak ceny, dostępność i recenzje. Podkreśla znaczenie korzystania z serwerów proxy i ich rotacji, aby zapobiec zablokowaniu przez środki antybotowe Airbnb.

Komentarze:

0 komentarze