Zum Inhalt

Wie kann ich warten, bis die Seite in Selenium geladen ist? Ein Leitfaden für Experten

Lassen Sie mich raten: Sie haben angefangen, eine Site mit Selenium zu scannen, und plötzlich stehen Sie vor gefürchteten Timeout-Fehlern, Ausnahmen aufgrund veralteter Elemente und fehlerhaften Locators. Klingt bekannt?

Viele von uns waren dort! Im heutigen dynamischen Web ist es für eine zuverlässige Automatisierung von entscheidender Bedeutung, richtig zu warten, bis die Seiten vollständig geladen sind, bevor sie interagieren.

In diesem umfassenden Leitfaden mit mehr als 3200 Wörtern werde ich meine über 5-jährige Tätigkeit als professioneller Web-Scraping-Experte nutzen, um die verschiedenen Methoden und Best Practices für elegantes Warten in Selenium zu erkunden.

Unabhängig davon, ob Sie gerade erst anfangen oder ein erfahrener Profi sind, ist eine robuste Wartelogik ein unverzichtbares Werkzeug für Stabilität. Lass uns eintauchen!

Warum Sie nicht einfach reinstürmen können

In den Anfängen des Webs bestanden Seiten größtenteils aus einfachem HTML, das sequentiell gerendert wurde. Scraper könnten sofort beim Laden der Seite mit dem Extrahieren beginnen.

Aber das heutige Web ist sehr dynamisch. Entsprechend Google-Forschungbeträgt die durchschnittliche Zeit bis zum ersten Malen 1.7 Sekunden, aber die durchschnittliche Zeit bis zur vollständigen Interaktion ist beeindruckend 15 Sekunden. Das Laden von Inhalten dauert sehr lange.

Wenn Sie als Scraper zu schnell vorgehen, sind hier einige häufige Probleme, mit denen Sie konfrontiert werden:

  • Fehler beim Klicken auf die Schaltfläche, da das Element noch nicht gerendert wurde
  • Es wird versucht, Daten aus einer Tabelle zu lesen, die keinen Serverinhalt geladen hat
  • Senden von Text an einen Eingang, der nicht auf dem Bildschirm sichtbar ist
  • Leere Elemente entfernen, die nach dem Laden der Seite gefüllt werden

Diese Art von Ausnahmen sind Symptome dafür, dass Sie länger warten müssen, bis die Seite bereit ist, bevor Sie interagieren.

In Zahlen: Seitenladezeiten

Um zu verstehen, wie lange wir möglicherweise warten müssen, schauen wir uns einige reale Kennzahlen zur Seitenladeleistung von an Bericht zum Stand des Webs 2020 von Akamai:

  • Mittlere Zeit bis zur Interaktion: 15er-Jahre
  • Durchschnittliches Seitengewicht: 2744KB
  • Durchschnittliche Anzahl an Anfragen: 105
  • Durchschnittliche Bilder pro Seite: 53
  • JavaScript-Bytes pro Seite: 453KB

Heutzutage sind die Seiten größer und komplexer, und nach der ersten Antwort fällt viel mehr Arbeit an. Für Schaber ist es wichtig, auf Interaktivität zu warten, nicht nur auf den ersten Anstrich.

Häufige Ausnahmen, die durch kein Warten verursacht werden

Hier sind einige spezifische Ausnahmen, die auftreten können, wenn Elemente noch nicht bereit sind:

  • StaleElementReferenceException – Element nach dem Abruf aus dem DOM entfernt
  • ElementNotInteractableException – Ich versuche, auf ein unsichtbares Element zu klicken
  • NoSuchElementException – Zeitüberschreitung bei der Suche, da das Element noch nicht vorhanden ist

Jeder dieser Punkte weist darauf hin, dass der Schaber länger warten muss.

Explizites Warten ist Ihr Freund

Um diese Fehler zu vermeiden, müssen wir warten, bis die Seite vollständig gerendert ist, bevor wir interagieren. Es gibt zwei Hauptansätze in Selenium:

Implizite Wartezeiten – Legen Sie eine globale Wartezeit für den Treiber fest

Explizite Wartezeiten – Warten Sie, bis bestimmte Bedingungen eintreten

In den meisten Fällen wird ein explizites Warten einem impliziten Warten vorgezogen. Lassen Sie uns verstehen, warum.

Implizites Warten: Der Sledgehammer-Ansatz

Implizite Wartezeiten legen eine Zeitüberschreitung für den Treiber fest, um das DOM abzufragen, wenn Elemente gefunden werden. Das bedeutet, wann immer Sie anrufen:

driver.find_element_by_id(‘some-id‘)

Der Treiber versucht bis zur impliziten Wartezeit, dieses Element zu finden, bevor er eine NoSuchElementException auslöst.

Sie könnten es wie folgt verwenden:

driver = webdriver.Chrome()
driver.implicitly_wait(10) 

Jetzt werden alle Suchvorgänge bis zu 10 Sekunden lang wiederholt, um Elemente zu finden, wenn sie nicht sofort vorhanden sind.

Der Nachteil besteht darin, dass auf jeden Locator gewartet wird, auch auf solche, die nicht zur Bestimmung der Seitenbereitschaft benötigt werden. Dies kann Ihren Scraper wirklich verlangsamen.

Stellen Sie sich implizite Wartezeiten wie das Hinzufügen eines Ruhezustands von 5 Sekunden zu jedem Elementabruf vor. Es summiert sich!

Die Präzision expliziter Wartezeiten

Explizites Warten ermöglicht es uns, genau auf bestimmte Bedingungen zu warten, die die Bereitschaft anzeigen, bevor wir fortfahren.

Die Kernideen sind:

  • Warten Sie nur, wenn es nötig ist – Vermeiden Sie unnötige Wartezeiten, die nichts mit der Seitenbereitschaft zu tun haben
  • Genaue Bedingungen – Warten Sie auf genaue Elemente oder Zustände, nicht nur auf die pauschale Zeit
  • Flexibilität – Passen Sie die Wartelogik pro Seite mit unterschiedlichen Bedingungen an
  • lesbar – Leicht verständliche Absicht beim erneuten Aufrufen von altem Code

Hier ist ein typisches Beispiel für das Warten auf das Erscheinen eines Elements:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait 

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "myDynamicElement"))
)

Dadurch wird die Ausführung angehalten, bis das Element mit der ID „myDynamicElement“ geladen wird oder 10 Sekunden verstrichen sind.

Weitere nützliche erwartete Bedingungen bereitgestellt von Selen -System umfasst:

  • title_contains() – Warten Sie, bis der Seitentitel aktualisiert wird
  • staleness_of() – Warten Sie, bis das Element nicht mehr an DOM angehängt ist
  • element_to_be_clickable() – Warten Sie, bis das Element sichtbar und aktiviert ist

Explizite Beats implizit: Ein Beispiel aus der Praxis

Vergleichen wir die beiden Wartezeiten mit einem realen Beispiel.

Angenommen, ich durchsuche eine Website, die über eine Navigationsleiste, einen linken Seitenbereich und einen Hauptinhalt verfügt.

Das Schlüsselelement, auf das ich warten muss, ist eine ID „#main-content“, unter der meine Daten gerendert werden.

Mit implizitem Warten:

  • 10 Sekunden werden zu jeder Elementsuche hinzugefügt, auch wenn sie nicht benötigt wird
  • Immer noch anfällig für veraltete Elementfehler, wenn es zu schnell geht

Mit explizitem Warten:

  • Warten Sie nur bei Bedarf auf #main-content selector
  • Vermeiden Sie unnötige Wartezeiten für Navigation und Seitenpanel
  • Warten Sie unbedingt, bis die Daten geladen sind, bevor Sie fortfahren

Indem ich selektiv auf eine einzelne Bereitschaftsbedingung wie ein Element warte, vermeide ich unnötige Verzögerungen.

Muster für effektives explizites Warten

Nachdem Sie nun davon überzeugt sind, dass explizite Wartezeiten der richtige Weg sind, wollen wir uns mit einigen Best Practices für deren effektive Nutzung befassen.

Das Laden der Seite wartet

Das Warten auf den Status „Bereit“ des Dokuments ist eine gängige Technik, um festzustellen, wann der Ladevorgang abgeschlossen ist:

WebDriverWait(driver, 10).until(
   lambda d: d.execute_script(‘return document.readyState‘) == ‘complete‘
)

Dadurch wird der Browser abgefragt, bis der Bereitschaftsstatus „abgeschlossen“ ist, was bedeutet, dass alle Assets geladen sind.

Ein leichteres Muster sucht nach bestimmten Elementen auf hoher Ebene:

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "main-content"))
) 

Dies gelingt, wenn der Hauptinhaltsabschnitt geladen wird, ohne auf alles andere warten zu müssen.

Wartezeiten pro Aktion

Sie können auch warten, bevor Sie eine Aktion ausführen, beispielsweise auf ein Element klicken:

menu = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "top-menu"))
)

submenu = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "submenu"))
)

submenu.click()

Dadurch wird sichergestellt, dass sowohl das Hauptmenü als auch das Untermenü bereit sind, bevor Sie darauf klicken.

Parallele Wartezeiten

Das Warten auf mehrere Bedingungen kann bestätigen, dass die Seite bereit ist:

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "header")),
    EC.presence_of_element_located((By.ID, "footer")), 
    EC.presence_of_element_located((By.ID, "main"))
)

Durch das Laden der Kopf- und Fußzeile sowie des Hauptinhalts werden Fehlalarme reduziert.

Verkettete und verschachtelte Wartezeiten

Für erweiterte Szenarios können Sie Wartezeiten auch verschachteln:

element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "dropdown"))
)

menu = WebDriverWait(element, 10).until(
    EC.presence_of_element_located((By.ID, "menu"))  
)

Dies wartet zuerst auf ein übergeordnetes Element und dann auf ein darin enthaltenes untergeordnetes Element.

AJAX-Abfrage wartet

Einige Websites werden über kontinuierliche AJAX-Anfragen geladen. Sie können eine Schleife ausführen, um auf Änderungen zu warten:

while True:

    current_count = driver.find_element_by_id(‘result-count‘).text

    # If count changed since last check, page is still loading
    if current_count != previous_count:
        previous_count = current_count
        continue 

    break # Page loaded!

Dadurch wird ein Element abgefragt, das nach Änderungen sucht, um das Laden zu erkennen.

Asynchrone Wartezeiten

In asynchronen Frameworks wie Asyncio können Sie auf Versprechen warten:

await page.waitForSelector(‘#content‘)

Die Syntax ist etwas anders, ermöglicht aber asynchrones Warten.

Implizite + explizite Kombination

Sie können sogar implizite und explizite Wartezeiten kombinieren:

driver.implicitly_wait(10) 

my_element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "my-element"))
)

Auf diese Weise haben Sie sowohl eine globale als auch eine spezifische Wartezeit. Stellen Sie einfach sicher, dass sie angemessene Zeiträume verwenden.

Wählen Sie Ortungsgeräte, die Bereitschaft signalisieren

Wenn Sie Locators auswählen, auf die gewartet werden soll, möchten Sie Elemente, die diesen Kriterien entsprechen:

  • Erscheint zu spät im Ladevorgang
  • Verfügen Sie über eindeutige IDs oder Klassen, die sich nicht ändern
  • Befindet sich über dem Falz für schnelle Kontrollen
  • Es ist unwahrscheinlich, dass sie aufgrund von Standortänderungen verlagert werden
  • Lassen Sie sich nicht aus dem DOM entfernen und veralten

Einige gängige Beispiele sind:

  • Hauptkopfzeile oder Navigation, die nach den Assets geladen wird
  • Primäre Inhaltscontainer oder Widgets
  • Fußzeile
  • Kleine dynamische UI-Elemente wie Schaltflächen

Ladeindikatoren wie Spinner sind auch tolle Warteauslöser, wenn sie verschwinden.

Zeitüberschreitungen für optimales Warten optimieren

Zu lange Zeitüberschreitungen können Ihren Scraper wirklich verlangsamen – zu kurze Zeitüberschreitungen können jedoch zu unregelmäßigen Ausfällen führen.

Hier sind einige Best Practices zum Optimieren der Dauer:

  • Stellen Sie die Seitenladezeitüberschreitungen länger ein, etwa 10–20 Sekunden.
  • Verwenden Sie kürzere Timeouts wie 3–5 Sekunden für einzelne Elemente.
  • Berücksichtigen Sie die Browserleistung, Mobilgerät vs. Desktop.
  • Berücksichtigen Sie die Netzwerklatenz, Breitband vs. 3G.
  • Überwachen Sie die Zeitüberschreitungsfehler und passen Sie sie bei Bedarf höher an.
  • Analysieren Sie den Seitenlade-Wasserfall für typische Ladezeiten.
  • Planen Sie 1–2 Sekunden zusätzlich als Puffer ein.
  • Standardisieren Sie ähnliche Wartezeiten in Ihrer gesamten Codebasis.

Wenn Sie mehr Seiten durchsuchen, erhalten Sie ein besseres Gespür für optimale Wartezeiten auf Zuverlässigkeit.

Behandeln von Warte- und Zeitüberschreitungsfehlern

Auch bei langen Wartezeiten kann es gelegentlich zu Zeitüberschreitungen kommen. Hier sind einige Möglichkeiten, damit umzugehen:

  • Debugging-Details protokollieren – Das Hinzufügen von Ausdrucken hilft bei der Diagnose, wo Wartezeiten fehlschlagen.
  • Bei Zeitüberschreitung erneut versuchen – Wiederholen Sie kurze explizite Wartezeiten bis zu dreimal, wenn ein Fehler auftritt.
  • Timeout erhöhen – Wenn viele Zeitüberschreitungen auftreten, erhöhen Sie die Wartezeiten schrittweise.
  • Verwenden Sie try/exclusive – Fangen Sie bestimmte Ausnahmen wie StaleElementReference ab.
  • Bei Fehler deaktivieren – Sie können Wartezeiten nach wiederholten Fehlern überspringen, um die Tests fortzusetzen.

Mit einer gewissen Widerstandsfähigkeit führen diese sporadischen Probleme nicht dazu, dass Ihr Schaber kaputt geht.

Warten in anderen Sprachen

Bisher waren die Beispiele in Python, aber explizite Wartezeiten sind in allen Sprachen verfügbar:

  • Javac - WebDriverWait und ExpectedConditions
  • C# - WebDriverWait und ExpectedConditions
  • Ruby - WebDriver::Wait und ExpectedConditions
  • JavaScript - browser.wait() und Utility-Methoden

Die Konzepte sind sehr ähnlich – lediglich die Syntax unterscheidet sich geringfügig.

Jenseits von Selen: Weitere Wartewerkzeuge

Neben Selenium gibt es noch einige andere hilfreiche Wartebibliotheken:

  • Uhrzeit - time.sleep() ist einfach, unterbricht jedoch die gesamte Ausführung.
  • Wiederholen - Die Paket erneut versuchen macht Wiederholungsversuche und Wartezeiten einfach.
  • Aiohttp - await response.text() wartet auf den Abschluss von Netzwerkaufrufen.
  • Schöne Suppe - BeautifulSoup(page.content, features="lxml") wird auf die vollständige Analyse warten.
  • Scrapy - yield scrapy.Request(url, callback=self.parse) ist asynchron.

Das Mischen dieser Elemente mit Selenium sorgt für robuste Wartezeiten im gesamten Code.

Fazit: Gut warten und zuverlässig verschrotten

Abschließend sind hier fünf wichtige Erkenntnisse:

  1. Verwenden Sie explizite Wartezeiten – Sie vermeiden unnötige Timeouts und zielen auf bestimmte Bedingungen ab.

  2. Warten Sie auf mehrere Signale – Combine wartet auf Kopfzeile, Textkörper, Fußzeile usw., um die Seitenbereitschaft zu bestätigen.

  3. Passen Sie Timeouts mit Bedacht an – Legen Sie Werte basierend auf realen Seitenladedaten fest, um Verzögerungen zu optimieren.

  4. Wartezeiten standardisieren – Verwenden Sie konsistente Muster in Ihrer gesamten Codebasis wieder.

  5. Fügen Sie Widerstandsfähigkeit hinzu – Implementieren Sie Wiederholungsversuche und Fehlerbehandlung, um dynamische Seiten zu berücksichtigen.

Das Warten mag zunächst mühsam erscheinen. Aber wenn Sie in eine robuste Wartelogik investieren, werden Sie mit zuverlässigen, widerstandsfähigen Scrapern belohnt, die für das moderne Web vorbereitet sind.

Hoffentlich helfen Ihnen diese Muster und Tipps aus meiner langjährigen Tätigkeit als professioneller Web-Scraping-Spezialist dabei, erfolgreich zu warten. Schrott weiter!

Stichworte:

Mitreden

E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind MIT * gekennzeichnet. *