<- Zurück

Selenium als Daten Crawling Library für JavaScript Websites


Um Daten von JavaScript-Webseiten in Python zu extrahieren, muss man häufig auf Selenium zurückgreifen, anstatt auf Standard Libraries wie urllib oder Beautiful Soup. Standard Libraries senden normalerweise einen Request an eine Webseite und laden den HTML-Code der Seite herunter, aus dem die Daten dann extrahiert werden können.

Das Problem bei JS-Seiten besteht allerdings darin, dass deren HTML-Code nicht die Daten enthalten müssen, die wir abrufen möchten. Stattdessen beinhaltet der HTML Code von JS-Seiten JavaScript-Code, der Daten dynamisch aus der Backend-Datenbank in die Seite ladet, jedoch nicht die Daten selbst. Um dieses Problem zu lösen, können wir die Libraries Selenium verwenden, die eine Vielzahl nützlicher Funktionen bietet. Eine Funktion davon erlaubt uns, Daten, die von JS aus dem Backend geladen wurden, zu extrahieren.

Mit Selenium können wir einen Web Browser in einen Roboter verwandeln, der durch eine Website navigiert, die Seiten und Daten rendered und dabei die Daten extrahiert. Mit Selenium können wir also den Browser steuern, wie z.B. auf Schaltflächen klicken oder Texte in Suchleisten eingeben. In einigen Fällen ist es beispielsweise erforderlich, sich in ein Benutzerkonto einzuloggen, um die Daten einsehen zu können oder spezifische Suchanfragen durchzuführen.

In diesem Beitrag zeige ich, wie man Unterkünfte auf der Webseite www.booking.com crawlt. Dabei instruieren wir unseren Selenium-Crawler, einen Ort in die Suchleiste einzugeben, ein Check-in-Datum auszuwählen und die Anzahl der Gäste anzugeben. Anschließend senden wir die Suchanfrage durch einen Button-Klick und crawlen die Unterkunftsdaten auf allen Ergebnisseiten.

Um unseren Selenium-Crawling-Bot zu erstellen, müssen wir zwei Dinge vorbereiten: (1) Zunächst müssen wir Selenium in Python installieren, indem wir den Command pip3 install selenium in der Kommandozeile ausführen. (2) In einem weiteren Schritt laden wir einen Webdriver wie den ChromeDriver herunter und speichern die heruntergeladene .exe-Datei im Projektverzeichnis, in dem sich das Python Skript befindet oder an einer anderen Stelle in unserer Verzeichnisstruktur. Beachtet werden sollte, dass der tatsächliche Browser zusätzlich zum Webdriver installiert sein muss. Falls Chrome als Browser verwendet wird, laden wir den ChromeDriver von der entsprechenden Quelle herunter. Hierbei sollte sichergestellt werden, dass die Version des Webdrivers mit der Version des installierten Browsers übereinstimmt.

In folgendem Beispiel crawlen wir Unterkunftsdaten für alle Distrikte in Irland von booking.com. Dazu erstellen wir eine .csv-Datei mit einer Liste aller irischen Distrikte. Diese .csv-Datei hilft uns, alle Distrikte in einem Loop zu crawlen. Die Liste der Distrikte kann von einer externen Quelle kopiert werden. Die .csv-Datei wird mit der Überschrift in der ersten Zeile als Counties.csv gespeichert.

Nun können wir mit der Entwicklung des Crawling Bots beginnen.

Zuerst importieren wir die für den Crawling-Bot erforderlichen Python Libraries.

import time
import pandas as pd
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support import expected_conditions as EC 

Im nächsten Schritt weisen wir einige Parameter Variablen zu, die vom Crawling-Bot verwendet werden und notwendig sind, um die Suchanfragen auszuführen. Außerdem definieren wir den Pfad, an dem sich der ChromeDriver befindet, und laden die Landkreise mit Pandas in das Programm.

url = "https://www.booking.com/"
checkin_month = "August 2022"
checkin_day = "26, Friday"
chrome_driver_path = Service("C:/Users/Documents/Python/Booking_Crawling/chromedriver")
df_counties = pd.read_csv('Counties.csv', usecols=['Counties'])

Nachdem wir die Variablen vorbereitet und die Distrikte geladen haben, starten wir einen Loop über die Distrikte. Beachtet werden sollte, dass die nächsten Codeblöcke innerhalb dieses äußeren Loops liegen. Zuerst erstellen wir eine Liste, in der die Daten während der Schleife gespeichert werden. Nach dem Start des Loops schreiben wir einen try/except-Block, um den offenen Webdriver der vorherigen Iteration zu schließen. In der ersten Iteration wird dieser Block übersprungen, da der Webdriver noch nicht gestartet wurde. Anschließend initialisieren wir den Webdriver und navigieren mit ihm zur booking.com-Website.


df_properties = []

for row in df_counties.iterrows():
        county_search = row[1]['Counties']

        try:
                driver.close()
        except Exception as e:
                print(e)

        try:
                driver = webdriver.Chrome(service=chrome_driver_path)
                driver.get(url)

Im nächsten Schritt instruieren wir Selenium, zu warten bis die Suchleiste von booking.com erscheint und senden den Namen des Districts in die Suchleiste.

                search_entry = wait(driver,20).until(EC.presence_of_element_located((By.ID, "ss")))
                search_entry.send_keys(county_search)

Anschließend wird der Webdriver angewiesen, den Date Picker zu finden und das Check-in-Datum einzugeben. Hier verwenden wir den CSS-Selector, um das Webelement zu finden. Dazu navigieren wir auf booking.com, klicken mit der rechten Maustaste auf die Seite und wählen „Inspect“, um den HTML-Code der Seite anzuzeigen. Sobald wir das Webelement im HTML-Code gefunden haben, kopieren wir den entsprechenden Selector. Dieser Prozess wird für alle anderen Webelemente wiederholt.

Nach der Eingabe des Distriktes in die Suchleiste legen wir das Check-in-Datum fest. Ein Check-out-Datum wird in diesem Fall nicht benötigt, da wir Daten nur für eine Nacht crawlen möchten.

                 Datebox_checkin_month = driver.find_element(By.CSS_SELECTOR, 
                         .div:nth-child(1) select:nth-child(2)) 
                 Datebox_checkin_month.send_keys(checkin_month) 
                 Datebox_checkin_day = driver.find_element(By.CSS_SELECTOR, 
                         "select:nth-child(2)") 
                 Datebox_checkin_day.send_keys(checkin_day) 
                 age_child1_input = wait(driver,20).until(EC.presence_of_element_located((By.CSS_SELECTOR, 
                         ".sb-group__children__field > select:nth-child(1)"))) 
                 age_child1_input.send_keys(10)

Im nächsten Schritt definieren wir die Anzahl der Personen. Für dieses Beispiel möchten wir Daten für zwei Erwachsene und zwei Kinder. Da booking.com standardmäßig zwei Erwachsene vorgibt, müssen wir nur die Anzahl der Kinder spezifizieren. Booking.com verlangt außerdem, dass wir das Alter der Kinder angeben. Schließlich instruieren wir den Crawling-Bot, auf die Schaltfläche „Suchen“ zu klicken und 3 Sekunden zu warten, bis die Suchergebnisse geladen sind.

                Number_of_guests = driver.find_element(By.CSS_SELECTOR, 
".xp__guests")

                Number_of_guests.click()
                add_child_button = wait(driver,20).until( 
EC.presence_of_element_located((By.CSS_SELECTOR, "div.sb-group__field:nth-child(2) > 
div:nth-child(1) > div:nth-child(2) > button:nth-child(4)"))
)

                add_child_button.click()
                add_child_button.click()

                age_child2_input = wait(driver,20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".sb-group__children__field > 
select:nth-child(2)")))
                age_child2_input.send_keys("10")

                Submit_button = wait(driver,20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".sb-searchbox__button"))
)
                Submit_button.click()

                time.sleep(3)

Sobald die Suchanfrage abgesendet und die Daten geladen wurden, starten wir das Crawlen der Daten und speichern sie in der Variable results.

                results = wait(driver,20).until(
EC.presence_of_element_located((By.CSS_SELECTOR, 
'[data-testid="property-card"]'))
)

Im nächsten Schritt beginnen wir mit einem inneren Loop, in der wir die Daten analysieren und diese in der zuvor erstellten Liste df_properties hinzufügen.

                for property in results:
                        propertyArr = property.text.split("\n")
                        print(propertyArr)
                        df_properties.append(propertyArr)

Anschließend starten wir einen inneren Loop, um die Daten der nächsten Seiten zu crawlen. Mit diesem Loop überprüfen wir, ob die Schaltfläche „Nächste Seite“ deaktiviert ist. Wenn sie deaktiviert ist, verlassen wir die Schleife und starten mit dem nächsten Landkreis im äußeren Loop. Ist die Schaltfläche jedoch aktiviert, crawlen wir die Daten der nächsten Seite und fügen sie der Liste df_properties hinzu.

                while True:
                        time.sleep(3)
                        if not (driver.find_element(By.CSS_SELECTOR, 
"[aria-label='Next page']").is_enabled()):                                
                                break                        
                        elm = driver.find_element(By.CSS_SELECTOR, "[aria-label='Next page']") 
                        elm.click()
                        time.sleep(3)
                        results = driver.find_elements(By.CSS_SELECTOR, 
'[data-testid="property-card"]')
                        print(results)
                        for property in results:
                                propertyArr = property.text.split("\n")
                                print(propertyArr)
                                df_properties.append(propertyArr)  
                                       
        except Exception as e:
                print(e)

Am Ende verwenden wir Pandas, um die Liste in einen DataFrame zu transformieren und in unserem Arbeitsverzeichnis zu speichern, nachdem sowohl der innere als auch der äußere Loop beendet wurden.

df_mydata = pd.DataFrame(df_properties)
df_mydata.to_csv(r'2_Adults_2_Kids_Booking_Data.csv', header=False, index=False)

Selenium ist eine sehr praktische Library, um Daten von JS-Webseiten zu extrahieren und einen Browser zu steuern. Die Fähigkeit, einen Browser zu steuern, ermöglicht es uns, verschiedene Webtools zu erstellen, wie beispielsweise Bots für das Website-Testing oder Chatbots für YouTube-Live-Chats. Den vollständigen Code finden Sie in meiner GitHub-Repository.

Apps

Connect

Mehr