Jak zeskrobać dane Booking.com za pomocą Pythona

Komentarze: 0

W tym artykule pokażemy, jak zbierać dane z witryny Booking.com za pomocą Pythona. Uzyskamy informacje obejmujące między innymi nazwy hoteli, oceny, ceny, adresy lokalizacji i ich opisy. Dostarczony kod umożliwia pobieranie danych ze stron hoteli poprzez analizowanie treści HTML i wyodrębnianie osadzonych danych JSON.

Instalacja wymaganych bibliotek

Przed uruchomieniem kodu do pobierania danych z Booking.com, należy zainstalować niezbędne biblioteki Python. Oto jak zainstalować wymagane zależności:

  1. Requests Biblioteka: Służy do wysyłania żądań HTTP do strony internetowej i pobierania zawartości HTML stron.
  2. LXML Biblioteka: Służy do analizowania zawartości HTML i wyodrębniania danych za pomocą XPath.
  3. JSON: Wbudowany moduł Pythona służący do obsługi danych JSON.
  4. CSV: Wbudowany moduł Pythona służący do zapisywania zeskrobanych danych do pliku CSV.

Aby zainstalować niezbędne biblioteki, można użyć pip:


pip install requests lxml

Są to jedyne zewnętrzne biblioteki, których potrzebujesz, a pozostałe (json, csv) są preinstalowane z Pythonem.

Zrozumienie adresu URL i struktury danych

Podczas skrobania danych z Booking.com ważne jest, aby zrozumieć strukturę strony internetowej i rodzaj danych, które chcesz wyodrębnić. Każda strona hotelu w Booking.com zawiera osadzone dane strukturalne w postaci JSON-LD, formatu, który umożliwia łatwe wyodrębnienie szczegółów, takich jak nazwa, lokalizacja i ceny. Będziemy pobierać te dane.

Proces scrapingu krok po kroku

Ponieważ Booking.com jest dynamiczną witryną i wdraża środki mające na celu zwalczanie zautomatyzowanych działań, użyjemy odpowiednich nagłówków HTTP i serwerów proxy, aby zapewnić płynne skrobanie bez ryzyka zablokowania.

Wysyłanie żądań HTTP z nagłówkami

Nagłówki naśladują sesję użytkownika w przeglądarce i zapobiegają wykryciu przez systemy anty-skrobakowe Booking.com. Bez odpowiednio skonfigurowanych nagłówków serwer może łatwo zidentyfikować zautomatyzowane skrypty, co może prowadzić do blokowania adresów IP lub wyzwań captcha.

Aby uniknąć zablokowania przez mechanizmy anty-scrapingowe Booking.com, użyjemy niestandardowych nagłówków do symulacji legalnego użytkownika przeglądającego witrynę. Oto jak wysłać żądanie HTTP z odpowiednimi nagłówkami:


import requests
from lxml.html import fromstring

urls_list = ["https links"]

for url in urls_list:
    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        'accept-language': 'en-IN,en;q=0.9',
        'cache-control': 'no-cache',
        'dnt': '1',
        'pragma': 'no-cache',
        'priority': 'u=0, i',
        'sec-ch-ua': '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Linux"',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'none',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
    }

    response = requests.get(url, headers=headers)

Ważność proxy

Korzystanie z serwerów proxy jest niezbędne podczas skrobania stron takich jak Booking.com, które stosują ścisłe limity żądań lub śledzą adresy IP. Serwery proxy pomagają rozłożyć obciążenie żądaniami na różne adresy IP, zapobiegając blokadom. W tym celu można korzystać zarówno z darmowych serwerów proxy, jak i płatnych usług proxy z uwierzytelnianiem za pomocą nazwy użytkownika i hasła lub adresu IP. W naszym przykładzie używamy tej drugiej opcji.


proxies = {
    'http': '',
    'https': ''
}
response = requests.get(url, headers=headers, proxies=proxies)

Parsowanie HTML i wyodrębnianie danych JSON

Po wysłaniu żądania analizujemy zawartość HTML za pomocą lxml, aby zlokalizować osadzone dane JSON-LD zawierające szczegóły hotelu. Ten krok wyodrębnia ustrukturyzowane dane ze strony internetowej, które zawierają nazwy hoteli, ceny, lokalizacje i inne.


parser = fromstring(response.text)

# Wyodrębnianie osadzonych danych JSON
embeded_jsons = parser.xpath('//script[@type="application/ld+json"]/text()')
json_data = json.loads(embeded_jsons[0])

Pobieranie informacji o hotelu

Po przeanalizowaniu danych JSON możemy wyodrębnić odpowiednie pola, takie jak nazwa hotelu, adres, ocena i cena. Poniżej znajduje się kod wyodrębniający informacje o hotelu z JSON:


name = json_data['name']
location = json_data['hasMap']
priceRange = json_data['priceRange']
description = json_data['description']
url = json_data['url']
ratingValue = json_data['aggregateRating']['ratingValue']
reviewCount = json_data['aggregateRating']['reviewCount']
type_ = json_data['@type']
postalCode = json_data['address']['postalCode']
addressLocality = json_data['address']['addressLocality']
addressCountry = json_data['address']['addressCountry']
addressRegion = json_data['address']['addressRegion']
streetAddress = json_data['address']['streetAddress']
image_url = json_data['image']
room_types = parser.xpath("//a[contains(@href, '#RD')]/span/text()")

# Dodanie danych do listy all_data
all_data.append({
    "Name": name,
    "Location": location,
    "Price Range": priceRange,
    "Rating": ratingValue,
    "Review Count": reviewCount,
    "Type": type_,
    "Postal Code": postalCode,
    "Address Locality": addressLocality,
    "Country": addressCountry,
    "Region": addressRegion,
    "Street Address": streetAddress,
    "URL": url,
    "Image URL": image_url,
    "Room Types": room_types
})

Zapisywanie danych do CSV

Po wyodrębnieniu danych możemy zapisać je do pliku CSV w celu dalszej analizy:


# Po przetworzeniu wszystkich adresów URL zapisz dane do pliku CSV
with open('booking_data.csv', 'w', newline='') as csvfile:
    fieldnames = ["Name", "Location", "Price Range", "Rating", "Review Count", "Type", "Postal Code", 
                  "Address Locality", "Country", "Region", "Street Address", "URL", "Image URL", "Room Types"]
    
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    
    # Napisz nagłówek
    writer.writeheader()
    
    # Zapis wierszy danych
    writer.writerows(all_data)

Kompletny kod

Oto kompletny kod łączący wszystkie sekcje:


import requests
from lxml.html import fromstring
import json
import csv

# Lista adresów URL hoteli do zeskrobania
urls_list = [
    "Https link", 
    "Https link"
]

# Zainicjuj pustą listę, aby pomieścić wszystkie zeskrobane dane
all_data = []

proxies = {
    'http': ''
}

# Pętla przez każdy adres URL w celu zeskrobania danych
for url in urls_list:
    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        'accept-language': 'en-IN,en;q=0.9',
        'cache-control': 'no-cache',
        'dnt': '1',
        'pragma': 'no-cache',
        'priority': 'u=0, i',
        'sec-ch-ua': '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Linux"',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'none',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
    }

    # Wysyłanie żądania do strony internetowej
    response = requests.get(url, headers=headers, proxies=proxies)
    
    # Analizowanie zawartości HTML
    parser = fromstring(response.text)
    
    # Wyodrębnianie osadzonych danych JSON
    embeded_jsons = parser.xpath('//script[@type="application/ld+json"]/text()')
    json_data = json.loads(embeded_jsons[0])

    # Wyodrębnij wszystkie szczegóły hotelu z JSON
    name = json_data['name']
    location = json_data['hasMap']
    priceRange = json_data['priceRange']
    description = json_data['description']
    url = json_data['url']
    ratingValue = json_data['aggregateRating']['ratingValue']
    reviewCount = json_data['aggregateRating']['reviewCount']
    type_ = json_data['@type']
    postalCode = json_data['address']['postalCode']
    addressLocality = json_data['address']['addressLocality']
    addressCountry = json_data['address']['addressCountry']
    addressRegion = json_data['address']['addressRegion']
    streetAddress = json_data['address']['streetAddress']
    image_url = json_data['image']

    room_types = parser.xpath("//a[contains(@href, '#RD')]/span/text()")
    
    # Dołączenie danych do listy all_data
    all_data.append({
        "Name": name,
        "Location": location,
        "Price Range": priceRange,
        "Rating": ratingValue,
        "Review Count": reviewCount,
        "Type": type_,
        "Postal Code": postalCode,
        "Address Locality": addressLocality,
        "Country": addressCountry,
        "Region": addressRegion,
        "Street Address": streetAddress,
        "URL": url,
        "Image URL": image_url,
        "Room Types": room_types
    })

# Po przetworzeniu wszystkich adresów URL zapisz dane do pliku CSV
with open('booking_data.csv', 'w', newline='') as csvfile:
    fieldnames = ["Name", "Location", "Price Range", "Rating", "Review Count", "Type", "Postal Code", 
                  "Address Locality", "Country", "Region", "Street Address", "URL", "Image URL", "Room Types"]
    
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    
    # Napisz nagłówek
    writer.writeheader()
    
    # Zapis wierszy danych
    writer.writerows(all_data)

print("Data successfully saved to booking_data.csv")

W tym artykule pokazaliśmy, jak skrobać dane hotelowe z Booking.com za pomocą Pythona. Podkreśliliśmy znaczenie używania odpowiednich nagłówków HTTP i serwerów proxy w celu ominięcia środków zapobiegających skrobaniu. Wyodrębnione dane można zapisać w pliku CSV w celu dalszej analizy. Podczas skrobania stron internetowych zawsze sprawdzaj warunki korzystania z usługi, aby uniknąć ich naruszenia.

Komentarze:

0 komentarze