Selenium steuert einen echten Browser. Das ist sein ganzer Daseinszweck beim Scraping: Wenn eine Seite ihren Inhalt mit JavaScript nach dem initialen HTML-Laden aufbaut, gibt eine einfache HTTP-Anfrage Ihnen eine leere Hülle, aber ein Browser führt die Skripte aus und gibt Ihnen das fertige DOM. Der Preis ist, dass Sie nun Chrome für jede Seite betreiben, was langsamer und schwerer als das Abrufen von HTML ist. Dieser Leitfaden baut einen funktionierenden Selenium-Scraper mit aktuellen Tools (Selenium 4) und zeigt dann, wo das eigenhändige Steuern eines Browsers nicht mehr lohnenswert ist.

Der Versionsunterschied ist hier wichtig. Die meisten Selenium-Tutorials lehren noch Selenium-3-Muster: find_element_by_id, manuell heruntergeladene ChromeDriver-Binärdateien, executable_path-Argumente. All das ist entfernt oder veraltet. Selenium 4 ersetzte die Find-Helfer durch eine einzige By-Locator-API, und Selenium Manager (seit 4.6 integriert) löst nun automatisch den richtigen Treiber für Ihren installierten Browser auf, sodass der Treiber-Download-Schritt, mit dem die meisten Leitfäden beginnen, entfällt. Alles unten ist für dieses aktuelle Setup geschrieben.

Was Sie benötigen

Drei Dinge: Python 3.8 oder neuer, Google Chrome installiert und das Selenium-Paket. Das war's. Sie müssen ChromeDriver nicht herunterladen und brauchen bei einer aktuellen Installation kein webdriver-manager, da Selenium Manager den Treiber für Sie verwaltet.

bash
# Selenium 4.6+ ships Selenium Manager, which resolves
# the matching driver for your installed Chrome.
pip install selenium
webdriver-manager bei neuen Projekten weglassen

Wenn Sie webdriver-manager in älteren Leitfäden gesehen haben, benötigen Sie es nicht mehr. Es löste dasselbe Problem, das Selenium Manager jetzt nativ löst. Behalten Sie es nur für Legacy-Code, der bereits davon abhängt; für alles Neue reicht eine Installation von selenium allein aus.

Headless Chrome starten

Selenium 4 konfiguriert den Browser über ein Options-Objekt, das an den Treiber übergeben wird. Beim Scraping wollen Sie fast immer den Headless-Modus (kein sichtbares Fenster), plus eine echte Fenstergröße und einen User-Agent, da einige Websites sich anders verhalten, wenn der Viewport winzig ist oder der Agent Automatisierung anzeigt.

python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1920,1080")
options.add_argument("--disable-gpu")
options.add_argument(
    "user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"
)

# No driver path needed. Selenium Manager resolves it.
driver = webdriver.Chrome(options=options)

Wenn Sie eine bestimmte Treiber-Binärdatei anpinnen müssen, geht das jetzt über ein Service-Objekt (webdriver.Chrome(service=Service("/path/to/chromedriver"), options=options)), nicht über das entfernte executable_path-Schlüsselwort. Für die meisten Leute ist es die richtige Wahl, Selenium Manager seine Arbeit machen zu lassen.

Eine Seite öffnen und Elemente lokalisieren

Mit einem Treiber zur Hand navigiert driver.get(url) und blockiert, bis das initiale Laden abgeschlossen ist. Dann finden Sie Elemente mit der By-API. Dies ist die einzige größte Änderung gegenüber Selenium 3: Jeder find_element_by_*-Helfer ist weg, ersetzt durch find_element(By.X, value).

python
from selenium.webdriver.common.by import By

driver.get("https://quotes.toscrape.com/")

# One element, then many.
title = driver.find_element(By.TAG_NAME, "h1").text
quotes = driver.find_elements(By.CLASS_NAME, "quote")

for q in quotes:
    text = q.find_element(By.CLASS_NAME, "text").text
    author = q.find_element(By.CLASS_NAME, "author").text
    print(author, "-", text)

Die nützlichsten Locators sind By.ID, By.CLASS_NAME, By.CSS_SELECTOR und By.XPATH. CSS-Selektoren decken die meisten Anforderungen ab und lesen sich sauber; greifen Sie auf XPath nur zurück, wenn Sie auf Textinhalt matchen oder nach oben zu einem Elternelement navigieren müssen, was CSS nicht kann. Beachten Sie, dass find_element eine Ausnahme auslöst, wenn nichts übereinstimmt, während find_elements eine leere Liste zurückgibt, also schleifen Sie über die Pluralform und prüfen Sie die Länge, anstatt einzelne Suchen in try/except zu verpacken.

Auf dynamischen Inhalt warten

Hier ist der Fehler, der die meisten Anfänger-Selenium-Scraper bricht: find_element sofort nach der Rückkehr von get() aufzurufen. Auf einer JavaScript-gerenderten Seite existiert das gewünschte Element möglicherweise noch nicht, und Sie erhalten eine NoSuchElementException auf einer Seite, die beim Betrachten problemlos lädt. Die Lösung ist ein explizites Warten, das polt, bis eine Bedingung wahr ist oder ein Timeout abläuft.

Greifen Sie nicht auf time.sleep() zurück. Ein fixer Schlaf verschwendet entweder Zeit, wenn die Seite schnell ist, oder schlägt fehl, wenn sie langsam ist; ein explizites Warten kehrt in dem Moment zurück, in dem das Element bereit ist, und tritt nur dann aus, wenn es wirklich nie erscheint.

python
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)

# Wait until at least one .quote is present in the DOM.
wait.until(
    EC.presence_of_element_located((By.CLASS_NAME, "quote"))
)

# Now it is safe to read the rendered content.
quotes = driver.find_elements(By.CLASS_NAME, "quote")

Verwenden Sie presence_of_element_located, wenn Sie das Element nur im DOM benötigen, und visibility_of_element_located oder element_to_be_clickable, wenn Sie Text lesen oder klicken wollen. Der Locator wird als Tupel übergeben, was ein leicht zu machender Fehler ist: Es ist ((By.CLASS_NAME, "quote")), ein Tupel-Argument, nicht zwei.

Paginierung verwalten

Die meisten echten Ziele verteilen Daten über mehrere Seiten. Das Muster ist eine Schleife: die aktuelle Seite scrapen, das Weiter-Steuerelement finden, darauf klicken, auf den neuen Inhalt warten, wiederholen, bis das Steuerelement weg ist. Die Falle ist, dass das Seitenobjekt nach der Navigation veraltet, sodass Sie den Weiter-Button bei jeder Iteration neu suchen, anstatt eine Referenz darauf zu halten.

python
from selenium.common.exceptions import NoSuchElementException

all_quotes = []

while True:
    wait.until(
        EC.presence_of_element_located((By.CLASS_NAME, "quote"))
    )
    for q in driver.find_elements(By.CLASS_NAME, "quote"):
        all_quotes.append(q.find_element(By.CLASS_NAME, "text").text)

    try:
        next_btn = driver.find_element(By.CSS_SELECTOR, "li.next a")
    except NoSuchElementException:
        break  # last page reached
    next_btn.click()

print("scraped", len(all_quotes), "quotes")
driver.quit()

Rufen Sie immer driver.quit() auf, wenn Sie fertig sind. Es schließt den Browser und den Treiberprozess; driver.close() schließt nur das aktuelle Fenster und lässt den Prozess laufen, was in einer Schleife schnell Chrome-Instanzen leckt. Für Infinite-Scroll-Seiten statt einem Weiter-Button ist das Äquivalent das Scrollen mit driver.execute_script("window.scrollTo(0, document.body.scrollHeight)") in einer Schleife und das Warten, bis die Elementanzahl aufhört zu wachsen.

Selenium durch einen Proxy leiten

Jedes Ziel in großem Volumen von einer IP scrapen und Sie werden rate-limitiert oder blockiert. Das Routing des Browsers über einen Proxy-Server verteilt Anfragen über verschiedene Adressen, sodass keine einzige ein Limit auslöst. Die einfachste Form übergibt den Proxy als Chrome-Argument.

python
options = Options()
options.add_argument("--headless=new")
options.add_argument("--proxy-server=http://proxy.example.com:8080")

driver = webdriver.Chrome(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element(By.TAG_NAME, "body").text)

Das funktioniert für einen nicht authentifizierten Proxy. Der Haken: Das --proxy-server-Flag von Chrome akzeptiert keinen Benutzernamen und kein Passwort in der URL, sodass ein authentifizierter Proxy eine Browser-Erweiterung benötigt, die den Auth-Header injiziert, oder ein lokales Relay, das die Zugangsdaten hält. Das ist eine der raueren Kanten beim direkten Steuern von Chrome. Ein rotierender Endpunkt, der sich per Token authentifiziert, umgeht das: Sie zeigen Selenium auf einen Host und die Rotation und das Vertrauen leben dahinter. Die Abwägungen zwischen der Verwaltung des eigenen Pools und der Verwendung eines verwalteten Endpunkts werden in Backconnect-Proxy vs. Crawling API behandelt, und wenn Ihre Ziele gehärtet sind, erklärt Datacenter vs. Residential Proxies, welchen IP-Typ Sie tatsächlich benötigen.

Wann ein Browser das falsche Werkzeug ist

Selenium ist richtig, wenn die Seite wirklich einen Browser benötigt: schweres clientseitiges Rendering, interaktionsgesperrte Inhalte oder Arbeitsabläufe, die vom Klicken und Tippen abhängen. Es ist das falsche Werkzeug, wenn Sie es aus Gewohnheit greifen. Wenn die Daten im initialen HTML sind, ist requests plus ein Parser um eine Größenordnung schneller und leichter. Und sobald ein Ziel mit ernsthaften Anti-Bot-Abwehren zurückschlägt, wird ein roher Headless-Browser sowieso gefingerprintet und blockiert, und Sie landen damit, Rotation, Wiederholungsversuche und Stealth von Hand neu aufzubauen.

Ansatz Rendert JS Geschwindigkeit / Kosten Am besten für
requests + Parser Nein Schnellste, leichteste Daten im initialen HTML, kein JS
Selenium Ja (echter Browser) Langsam, schwer JS-Rendering, Klicks, Formulare, Logins
Verwaltete Crawling API Ja (serverseitig) Eine Anfrage, keine Infra Gehärtete Ziele, Skalierung, keine Browser-Flotte

Die dritte Zeile ist, wo das meiste Produktions-Scraping landet. Eine verwaltete Crawling API rendert die Seite serverseitig, rotiert IPs, wiederholt bei Sperren und gibt Ihnen fertiges HTML aus einer einzigen Anfrage, sodass Sie niemals eine Browser-Flotte betreiben oder fingerabdruckabsichern müssen. Sie behalten Selenium für echte Interaktionsarbeit und lagern die hochvolumige, geblockte Arbeit an die API aus.

Crawlbase Crawling API

Wenn die Seite JavaScript benötigt, Sie aber lieber keine Browser-Flotte betreiben möchten, rendert die Crawling API sie serverseitig, rotiert IPs und wiederholt bei Sperren, und gibt fertiges HTML aus einer einzigen Anfrage zurück. Senden Sie eine URL mit &javascript=true und überspringen Sie die Headless-Infrastruktur vollständig. Probieren Sie es im kostenlosen Tarif gegen Ihr echtes Ziel.

Der Aufruf ist eine einzige HTTP-Anfrage, kein Treiber, keine Wartezeiten, kein Proxy-Auth-Tanz: Senden Sie Ihr Token und die Ziel-URL, fordern Sie Rendering an und lesen Sie den Body zurück.

python
import requests

resp = requests.get(
    "https://api.crawlbase.com/",
    params={
        "token": "_YOUR_TOKEN_",
        "url": "https://quotes.toscrape.com/js/",
        "javascript": "true",  # render the page server-side
    },
)
print(resp.status_code)
print(resp.text[:500])

Dasselbe gerenderte Ergebnis, das Sie von Selenium erhalten würden, ohne den Browser, die expliziten Wartezeiten oder die Proxy-Auth-Umgehung. Für einen tieferen Vergleich zwischen dem Betreiben des eigenen Pools und einem Endpunkt, der den gesamten Job übernimmt, lesen Sie die besten Proxies für Web-Scraper.

Zusammenfassung

Wichtigste Erkenntnisse

  • Selenium-4-Muster verwenden. Die By-Locator-API ersetzte jeden find_element_by_*-Helfer, und Selenium Manager löst den Treiber auf, sodass der manuelle Download-Schritt entfällt.
  • Den Browser über Options konfigurieren. Headless-Modus, eine echte Fenstergröße und ein User-Agent sind die Baseline für Scraping.
  • Explizit warten, niemals schlafen. WebDriverWait plus expected_conditions kehrt in dem Moment zurück, in dem der Inhalt bereit ist, und ist die Lösung für JS-Render-Wettlaufbedingungen.
  • Elemente nach der Navigation neu suchen. Referenzen veralten über Seiten hinweg; suchen Sie das Weiter-Steuerelement bei jeder Schleife neu und rufen Sie driver.quit() am Ende auf.
  • Ein Browser ist nicht immer die Antwort. Verwenden Sie requests, wenn die Daten im HTML sind, und eine verwaltete Crawling API, wenn Ziele gehärtet sind oder Sie Skalierung ohne eine Browser-Flotte benötigen.

Häufig gestellte Fragen

Muss ich ChromeDriver noch für Selenium 4 herunterladen?

Nein. Seit Selenium 4.6 erkennt der integrierte Selenium Manager Ihr installiertes Chrome und lädt den passenden Treiber automatisch herunter, sodass ein einfaches pip install selenium ausreicht. Sie geben einen Treiberpfad über ein Service-Objekt nur dann an, wenn Sie absichtlich eine bestimmte Binärdatei anpinnen müssen; das alte executable_path-Schlüsselwort wurde entfernt.

Warum wirft find_element NoSuchElementException auf einer Seite, die problemlos lädt?

Weil das Element nach dem initialen Laden durch JavaScript gerendert wird und Ihr Code das DOM abgefragt hat, bevor es existierte. Ersetzen Sie die sofortige Suche durch ein explizites Warten: WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "quote"))). Das Warten pollt, bis das Element erscheint oder das Timeout abläuft, was sowohl feste Schlafs als auch Wettlaufbedingungen vermeidet.

Sollte ich Selenium oder BeautifulSoup für Web Scraping verwenden?

Verwenden Sie requests mit einem Parser wie BeautifulSoup, wenn die Daten im initialen HTML der Seite vorhanden sind; es ist weit schneller und leichter, da es niemals einen Browser startet. Verwenden Sie Selenium, wenn der Inhalt durch JavaScript gerendert wird oder Sie klicken, tippen, scrollen oder sich einloggen müssen. Viele Scraper kombinieren beides: Selenium rendert die Seite, dann parst BeautifulSoup das resultierende HTML.

Wie verwende ich einen authentifizierten Proxy mit Selenium?

Das --proxy-server-Argument von Chrome akzeptiert keinen Benutzernamen und kein Passwort in der URL, sodass ein authentifizierter Proxy eine Browser-Erweiterung benötigt, die den Auth-Header injiziert, oder ein lokales Relay, das die Zugangsdaten hält. Ein Token-authentifizierter rotierender Endpunkt vermeidet das Problem: Sie zeigen Selenium auf einen Host und die Zugangsdaten leben dahinter, anstatt in den Start-Flags.

Ist Selenium gut für Scraping in großem Maßstab?

Es skaliert schlecht. Jede Seite betreibt einen vollständigen Browser, was langsam und speicherhungrig ist, und auf gehärteten Zielen wird ein roher Headless-Browser trotzdem gefingerprintet und blockiert. Für hohes Volumen ist eine verwaltete Crawling API, die serverseitig rendert, IPs rotiert und bei Sperren wiederholt, in der Regel die bessere Wahl, und Selenium bleibt für wirklich interaktionslastige Arbeit.

Was ist der Unterschied zwischen driver.close() und driver.quit()?

driver.close() schließt das aktuelle Browser-Fenster, lässt aber den Treiberprozess und alle anderen Fenster laufen. driver.quit() schließt jedes Fenster und beendet den Treiberprozess. Beenden Sie in einer Scraping-Schleife immer mit driver.quit(), sonst häufen sich verwaiste Chrome-Prozesse an und erschöpfen den Arbeitsspeicher.

Jetzt loslegen

Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.

Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.

Self-Service · Kein Verkaufsgespräch erforderlich · Enterprise-Crawl-Volumen verfügbar