Playwright oder Selenium: Welches Werkzeug passt?

Veröffentlicht:

19 Min. Lesezeit

Acar Diveroli
Autor: Acar Diveroli
Zwei gestapelte Automatisierungskarten: vorn Playwright mit blauem Treiberchip, dahinter halb sichtbar Selenium

Sie beginnen ein neues Projekt zur Datenerhebung oder zum Testen, und die Seite wird mit JavaScript aufgebaut, also brauchen Sie einen echten Browser. Im Team schreibt jemand seit Jahren Selenium, die neue Entwicklerin schlägt Playwright vor. Beide öffnen den Browser aus dem Code heraus und klicken darin, beide sind kostenlos; genau diese Ähnlichkeit macht die Wahl schwer. Die meisten Vergleiche betrachten das Thema mit dem Blick des Testens und lassen die Punkte aus, die bei der Datenerhebung den Ausschlag geben, etwa Proxys und das Warten.

In diesem Beitrag vergleichen wir die beiden Werkzeuge auf sieben Achsen: Architektur, automatisches Warten, Proxy-Verwaltung, Sprachunterstützung, Browser-Einrichtung, Parallelität und Fehlersuche. Den Code, der dieselbe kleine Aufgabe in beiden Werkzeugen erledigt, haben wir mit Playwright 1.63, Selenium 4.49 und Chrome 153 unter Windows 11 ausgeführt; was wir dabei gesehen haben, steht in den jeweiligen Abschnitten. „Welches fällt weniger auf" ist nicht das Thema dieses Beitrags: Beide Werkzeuge öffnen einen echten Browser, und in beiden ist es Ihre Aufgabe, die Regeln der Website einzuhalten.

Was sind Playwright und Selenium?

Selenium ist ein quelloffenes Projekt zur Browser-Automatisierung, das seit 2004 entwickelt wird. Der heute genutzte Teil ist Selenium WebDriver: Ihr Code schickt Befehle an einen Browsertreiber, und der Treiber steuert den Browser. Die Einrichtung behandelt unser Beitrag Selenium mit Proxy; Treiberdownload und Authentifizierung stehen dort ausführlich.

Playwright ist eine quelloffene Bibliothek zur Browser-Automatisierung, die Microsoft 2020 veröffentlicht hat. Sie steuert die Engines Chromium, Firefox und WebKit über eine einzige API. Installation und Proxy-Einstellungen stehen in Was ist Playwright und wie nutzt man es mit Proxy?; hier behandeln wir nur die Punkte, an denen es sich von Selenium unterscheidet.

Beide beantworten denselben Bedarf: Inhalte, die mit einer einfachen HTTP-Anfrage nicht kommen und erst entstehen, wenn im Browser JavaScript läuft. Ob die Seite wirklich einen Browser braucht, klären Sie mit der Prüfung aus Statische und dynamische Seiten beim Web Scraping. Steht die Information im Quelltext der Seite, ist ein einfacher HTTP-Client oder Scrapy günstiger als beide Werkzeuge.

Worin liegt der Architekturunterschied: WebDriver, BiDi und CDP

Fast jeder Verhaltensunterschied der beiden Werkzeuge entsteht daraus, wie sie mit dem Browser sprechen.

In Selenium nimmt ein Befehl diesen Weg:

  1. Ihr Code ruft driver.find_element(...) auf.
  2. Die Selenium-Bibliothek macht daraus eine HTTP-Anfrage aus dem W3C-WebDriver-Standard.
  3. Die Anfrage geht an das Treiberprogramm des Browserherstellers: ChromeDriver für Chrome, GeckoDriver für Firefox.
  4. Der Treiber wendet den Befehl auf den Browser an und schickt das Ergebnis als HTTP-Antwort zurück.

Jeder Befehl ist eine eigene Anfrage samt Antwort; der Browser kann Ihnen von sich aus nichts mitteilen. Ein Fehler in der Konsole oder eine Netzwerkanfrage im Hintergrund bleibt unsichtbar, solange Sie nicht danach fragen. Um diese Lücke zu schließen, schreibt das Selenium-Projekt gemeinsam mit den Browserherstellern den Standard WebDriver BiDi: ein bidirektionales Protokoll über WebSocket. In Selenium 4 schalten Sie es mit options.enable_bidi = True ein; weil der Übergang noch läuft, leben in Selenium heute zwei Welten nebeneinander.

Bei Playwright verläuft der Weg anders:

  1. Ihr Code ruft page.locator(...).click() auf.
  2. Die Bibliothek für Python, Java oder .NET reicht diesen Aufruf an den im Paket enthaltenen Playwright-Treiber weiter. Der Treiber ist ein Node.js-Prozess; in der virtuellen Umgebung liegt er als playwright/driver/node.exe.
  3. Der Treiber spricht über eine dauerhafte Verbindung mit dem Browser. In Chromium ist das das Chrome DevTools Protocol (CDP). Für Firefox und WebKit nutzt Playwright eigene, gepatchte Browser-Builds.
  4. Weil die Verbindung bidirektional ist, fließen Ereignisse im Browser (Anfrage, Antwort, Konsolenmeldung, Download) in Ihren Code, ohne dass Sie danach fragen.

Diese Entscheidung hat ihren Preis. Das Browser-Dokument von Playwright sagt es deutlich: Weil es auf Patches beruht, funktioniert es nicht mit dem markengebundenen Firefox und Safari. Chrome und Edge können Sie über die Option channel nutzen, doch den Bedarf „Test im echten Safari" deckt ein WebKit-Build nicht ab; Selenium steuert das installierte Safari über Apples eigenen Treiber.

Vergleichstabelle

PlaywrightSelenium
ProtokollDauerhafte Verbindung; in Chromium CDP, in Firefox und WebKit gepatchte BuildsW3C WebDriver (HTTP), daneben das entstehende WebDriver BiDi (WebSocket)
ZwischenschichtIm Paket enthaltener Playwright-TreiberTreiber des Browserherstellers (ChromeDriver, GeckoDriver)
BrowserChromium, Firefox, WebKit; mit channel Chrome und EdgeChrome, Edge, Firefox, Safari
Offizielle SprachenJavaScript und TypeScript, Python, Java, .NETJava, Python, C#, Ruby, JavaScript
WartenVor Aktionen von selbstSie schreiben es: WebDriverWait
Proxy-ReichweitePro Browser oder pro ContextPro Browser-Sitzung
Proxy-Benutzername und -PasswortEigene Felder im proxy-ObjektKein Feld im Standard; praktischer Weg ist die IP-Whitelist
Anfragen mithören und blockierenEingebaut (route, expect_response)Kommt mit BiDi; im klassischen WebDriver nicht vorhanden
Browser-Einrichtungplaywright install, an die Version gebundene BuildsSelenium Manager lädt den Treiber selbst und nutzt den installierten Browser
ParallelitätViele Contexts in einem BrowserEin Browser pro Aufgabe; über Maschinen hinweg Selenium Grid
FehlersucheTrace Viewer, Inspector, codegenBildschirmfoto, Browser-Log, Selenium IDE

Wie schreibt man dieselbe Aufgabe in beiden Werkzeugen?

Unsere Testseite ist quotes.toscrape.com/js-delayed/: eine Übungsseite, die ihre Zitate mit JavaScript und zehn Sekunden Verzögerung ausgibt. Die Aufgabe: Seite über einen Proxy öffnen, Zitate lesen, auf den Link „Next" klicken, die zweite Seite prüfen.

Mit Playwright:

python
from playwright.sync_api import sync_playwright

URL = "https://quotes.toscrape.com/js-delayed/"
PROXY = {
    "server": "http://pr.proxynet.io:8000",
    "username": "user",
    "password": "pass",
}

with sync_playwright() as p:
    browser = p.chromium.launch(proxy=PROXY)
    page = browser.new_page()
    page.goto(URL)
    quotes = page.locator("div.quote")
    print("immediately:", quotes.count())  # 0: count() wartet nicht
    quotes.first.wait_for()  # wartet, bis das erste Zitat auf der Seite steht
    for quote in quotes.all():
        text = quote.locator("span.text").inner_text()
        author = quote.locator("small.author").inner_text()
        print(author, "-", text[:50])
    page.get_by_role("link", name="Next").click()  # wartet vor dem Klick von selbst
    page.wait_for_url("**/page/2/")
    print(page.url)
    browser.close()

Mit Selenium:

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

URL = "https://quotes.toscrape.com/js-delayed/"

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
# Kein Benutzername, kein Passwort: Ihre Ausgangs-IP muss im Panel auf der IP-Whitelist stehen
options.add_argument("--proxy-server=http://pr.proxynet.io:8000")

driver = webdriver.Chrome(options=options)  # den Treiber findet Selenium Manager
try:
    driver.get(URL)
    print("immediately:", len(driver.find_elements(By.CSS_SELECTOR, "div.quote")))  # 0
    wait = WebDriverWait(driver, 15)
    quotes = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div.quote")))
    for quote in quotes:
        text = quote.find_element(By.CSS_SELECTOR, "span.text").text
        author = quote.find_element(By.CSS_SELECTOR, "small.author").text
        print(author, "-", text[:50])
    wait.until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "Next"))).click()
    wait.until(EC.url_contains("/page/2/"))
    print(driver.current_url)
finally:
    driver.quit()

Beide Skripte gaben über unsere lokalen Test-Proxys dieselben zehn Zitate aus und wechselten zu /js-delayed/page/2/. Die Zeilenzahl liegt nahe beieinander; der Unterschied steckt im Detail. Bei Playwright stehen die Proxy-Zugangsdaten im Code, bei Selenium nicht; der Klick ist bei Playwright eine Zeile, bei Selenium schreiben Sie die Bedingung für die Klickbarkeit von Hand. In beiden Skripten gab die Zeile „immediately" eine 0 zurück: Die Seite gilt als geladen, der Inhalt ist aber noch nicht da. Das ist das Thema des nächsten Abschnitts.

Worin unterscheiden sich automatisches Warten und WebDriverWait?

Auf dynamischen Seiten entstehen die meisten Fehler aus dem Timing: Der Code sucht ein Element, das JavaScript noch nicht ausgegeben hat. Das Warte-Dokument von Selenium nennt das eine Race Condition; mal ist der Browser zuerst bereit und der Code läuft, mal ist der Code schneller und Sie bekommen einen Fehler.

In Selenium liegt die Lösung in Ihrer Hand. driver.get() wartet auf das load-Ereignis der Seite, weiß aber nichts von Inhalten, die JavaScript später einfügt. Der Standardwert des impliziten Wartens ist null; fehlt das Element, kommt der Fehler sofort zurück. Empfohlen wird das explizite Warten: WebDriverWait fragt die Seite ab, bis eine Bedingung zutrifft. Das Dokument gibt noch eine Warnung: Verwenden Sie beides nicht zusammen, sonst werden die Zeiten unvorhersehbar.

Playwright legt dieselbe Arbeit in die Aktion hinein. Laut Actionability-Dokument wartet ein click()-Aufruf, bis das Element sichtbar ist, seine Position stabil ist, es den Klick annehmen kann und aktiv ist; werden die Bedingungen nicht rechtzeitig erfüllt, wirft er einen TimeoutError. Auch Aufrufe, die mit einem einzelnen Element arbeiten, etwa fill() und inner_text(), warten auf das Erscheinen des Elements.

Das hat eine Grenze: Das automatische Warten gilt für Aktionen, nicht für Zählungen. Im Beispiel oben gab quotes.count() ohne Warten eine 0 zurück. Das API-Dokument von Playwright hält dieselbe Anmerkung für locator.all() fest: Es wartet nicht auf passende Elemente, sondern liefert, was in dem Moment auf der Seite steht. Wollen Sie eine Liste lesen, warten Sie zuerst mit first.wait_for() auf das erste Element. Der Satz „in Playwright schreibt man kein Warten" stimmt deshalb nur halb.

Der zweite Unterschied liegt beim Elementverweis. In Selenium liefert find_element einen Verweis auf den DOM-Knoten in seinem damaligen Zustand; zeichnet die Seite diesen Bereich neu, veraltet der Verweis und Sie bekommen eine StaleElementReferenceException. In Playwright ist ein locator eine Beschreibung, die bei jeder Nutzung neu aufgelöst wird; derselbe Fehler tritt kaum auf. Die Sprache der Selektoren bleibt in beiden Werkzeugen Ihnen überlassen: CSS-Selektor oder XPath: Was passt zum Web Scraping?.

Wie unterscheidet sich die Proxy-Verwaltung?

Die Playwright-Seite haben wir im Schwesterbeitrag beschrieben, hier die Zusammenfassung: Das proxy-Objekt wird an launch() oder new_context() übergeben, username und password sind eigene Felder, und in einem Browser kann jeder Context über eine andere IP hinausgehen. Ein Context isoliert Cookies, Speicher und Proxy. Weil Browser und Maschine gleich bleiben, ändert sich der Browser-Fingerabdruck zwischen Contexts nicht; ein Context ist ein Sitzungstrenner, kein eigenes Gerät.

In Selenium ist der Proxy eine Sitzungsfähigkeit (Capability): Er wird beim Start des Browsers übergeben und bindet alle Tabs dieses Browsers; für einen anderen Proxy schließen Sie ihn mit driver.quit() und öffnen einen neuen Browser. Die Authentifizierung fehlt im Standard selbst. Die Proxy-Definition des W3C-WebDriver zählt die Schlüssel httpProxy, sslProxy, socksProxy, socksVersion und noProxy auf; einen Schlüssel für Benutzername oder Passwort gibt es nicht. Auch das offizielle Beispiel von Selenium zeigt nur die Form <HOST:PORT>. Der Standard sagt, die Serveradresse könne Zugangsdaten tragen, doch das Proxy-Dokument von Chromium hält fest, dass Chrome in den Proxy-Einstellungen eingebettete Zugangsdaten nicht verwendet.

Wohin das in der Praxis führt, haben wir mit einem lokalen Proxy mit Authentifizierung geprüft. Die Ergebnisse stammen aus Einzelläufen auf dieser Maschine (Selenium 4.49, Chrome 153):

Was wir versucht habenWas passiert ist
--proxy-server=http://server:port, keine ZugangsdatenDer Proxy gab 407 zurück. driver.get() warf keinen Fehler; die Seite blieb leer, driver.title kam leer zurück
--proxy-server=http://user:pass@server:portChrome öffnete die Fehlerseite ERR_NO_SUPPORTED_PROXIES, wieder ohne Ausnahme
user:pass@server:port im Proxy-ObjektDie Seite öffnete sich, doch im Proxy-Log stand keine einzige Anfrage: Der Browser verband sich direkt, mit unserer eigenen IP
Port ohne Authentifizierung (entspricht der IP-Whitelist)Lief ohne Probleme

Die dritte Zeile ist die gefährlichste: Das Skript sieht aus, als liefe es, dabei geht der Verkehr nicht über den Proxy. Ein Chrome-Argument namens --proxy-auth, das in älteren Beiträgen auftaucht, gibt es ebenfalls nicht. Der Aufruf add_auth_handler auf der BiDi-Seite von Selenium wird in der Dokumentation für die Basic-Authentifizierung der Website selbst beschrieben; für Proxys ist er kein dokumentierter Weg, und unser Versuch mit definiertem Proxy endete in einer Zeitüberschreitung beim Laden der Seite.

Deshalb empfehlen wir in Selenium die IP-Whitelist: Sie tragen die Ausgangs-IP des Servers, auf dem das Skript läuft, im Panel in die Liste ein und geben den Wert von --proxy-server ohne Zugangsdaten an. Der Vergleich der beiden Verfahren steht in Proxy-Authentifizierung: User:Pass oder IP-Whitelist, die Proxy-Syntax von SeleniumBase in Proxy mit SeleniumBase: Anmeldung und Rotation.

In denselben Läufen haben wir noch etwas beobachtet: Das installierte Chrome, das Selenium öffnete, verband sich neben der Zielseite auch mit den Update- und Kontodiensten von Google über den Proxy; im eigenen Chromium-Build von Playwright standen im Proxy-Log nur die Anfragen der Seite. Wenn Sie den Verkehr pro Gigabyte bezahlen, etwa bei Residential-Proxy, lohnt es sich, diesen Hintergrundverkehr im Panel zu beobachten.

Sprachunterstützung und Ökosystem

Die offiziellen Bibliotheken von Selenium gibt es für Java, Python, C#, Ruby und JavaScript. Die von Playwright für JavaScript und TypeScript, Python, Java und .NET. Sind Sie ein Ruby-Team, entscheidet sich die Sache von selbst.

Auch wenn sich die Sprachen auf dem Papier überschneiden, liegen die Schwerpunkte anders. Selenium ist ein zwanzig Jahre altes Projekt; ein großer Teil der Testteams in Unternehmen schreibt Selenium in Java oder C#, es gibt mit TestNG, JUnit, NUnit und Cucumber gebaute Suiten mit Hunderten von Szenarien, und sie neu zu schreiben kostet meist mehr, als Playwright an Bequemlichkeit bringt. Das reifste Gesicht von Playwright ist die Node.js-Seite: Der eigene Test-Runner bringt paralleles Ausführen, den Vergleich von Bildschirmfotos und die automatische Trace-Aufzeichnung mit. In Python ist das pytest-Plugin der empfohlene Weg. Datenerhebung mit C# behandeln wir in Daten von Websites holen mit C#: HttpClient und Proxy.

Beim Scraping geht die Wahl der Sprache oft der Wahl des Werkzeugs voraus: Liegt die Strecke, die die Daten verarbeitet, in Python, taugen beide Werkzeuge; liegt sie in Node.js, wirkt Playwright natürlicher. Der Vergleich der beiden Sprachen steht in Web Scraping: JavaScript oder Python?.

Browser-Einrichtung: Selenium Manager und playwright install

Ältere Selenium-Anleitungen sagen Ihnen, Sie sollten den zu Ihrer Chrome-Version passenden ChromeDriver von Hand herunterladen und seinen Pfad mit executable_path übergeben. Beides liegt hinter uns: In Selenium 4.49 nimmt webdriver.Chrome() nur die Parameter options, service und keep_alive an, und das Auffinden des Treibers erledigt seit Version 4.6 der mit der Bibliothek gelieferte Selenium Manager: Er erkennt die Version des installierten Browsers, lädt den passenden Treiber herunter und legt ihn im Ordner ~/.cache/selenium ab. In unserem Versuch lud er für das installierte Chrome 153 ohne Zusatzschritt den ChromeDriver 153 herunter. Laut Dokument kann er Chrome, Firefox und Edge auch herunterladen, wenn der Browser nicht installiert ist; das Werkzeug wird weiterhin als Beta versioniert.

Der Ansatz von Playwright ist umgekehrt: Es vertraut dem Browser auf dem System nicht. playwright install chromium lädt den eigenen Build herunter, und jede Playwright-Version ist an einen bestimmten Browser-Build gebunden. Aktualisieren Sie die Bibliothek und vergessen den Befehl install, bekommen Sie den Fehler „Executable doesn't exist"; uns ist das bei den Versuchen zu diesem Beitrag ebenfalls passiert.

Der Tausch ist dieser: Selenium fährt den Browser, den Ihre Nutzer tatsächlich verwenden und der sich selbst aktualisiert, was für Tests sinnvoll ist, aber bei einem Browser-Update kann sich das Verhalten ändern. In Playwright wird die Browserversion mit dem Code festgezurrt; wann aktualisiert wird, entscheiden Sie.

Parallel arbeiten: Grid oder Context?

In Playwright ist die Einheit der Parallelität der Context. Ein Browserprozess öffnet sich, jede Aufgabe bekommt ihren eigenen Context und auf Wunsch ihren eigenen Proxy:

python
import asyncio

from playwright.async_api import async_playwright

URLS = [f"https://quotes.toscrape.com/js/page/{n}/" for n in range(1, 4)]
PROXY = {"server": "http://pr.proxynet.io:8000", "username": "user", "password": "pass"}


async def scrape(browser, url):
    context = await browser.new_context(proxy=PROXY)  # isolierte Sitzung mit eigenem Proxy
    try:
        page = await context.new_page()
        await page.goto(url)
        quotes = page.locator("div.quote span.text")
        await quotes.first.wait_for()
        return url, await quotes.count()
    finally:
        await context.close()


async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()  # ein einziger Browserprozess
        for url, count in await asyncio.gather(*(scrape(browser, u) for u in URLS)):
            print(url, count)
        await browser.close()


asyncio.run(main())

In Selenium ist die Einheit der Browser selbst. Dieselbe Aufgabe schreibt man mit einem Thread-Pool, der pro Aufgabe einen Treiber öffnet:

python
from concurrent.futures import ThreadPoolExecutor

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

URLS = [f"https://quotes.toscrape.com/js/page/{n}/" for n in range(1, 4)]


def scrape(url):
    options = webdriver.ChromeOptions()
    options.add_argument("--headless=new")
    options.add_argument("--proxy-server=http://pr.proxynet.io:8000")  # mit IP-Whitelist
    driver = webdriver.Chrome(options=options)  # ein Browserprozess pro Aufgabe
    try:
        driver.get(url)
        quotes = WebDriverWait(driver, 15).until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div.quote span.text"))
        )
        return url, len(quotes)
    finally:
        driver.quit()


with ThreadPoolExecutor(max_workers=3) as pool:
    for url, count in pool.map(scrape, URLS):
        print(url, count)

Beide Skripte lieferten von drei Seiten je zehn Zitate. Der Unterschied liegt im Ressourcenverbrauch: Beim ersten öffnet sich ein Browser, beim zweiten drei Browser und drei Treiberprozesse. Bei zwanzig gleichzeitigen Sitzungen schlägt dieser Unterschied direkt auf den Speicher durch. Wann Nebenläufigkeit und Parallelität beim Scraping nützen, steht in Concurrency und Parallelism: Was bestimmt Scraping-Tempo?.

Stark ist Selenium bei der Verteilung über Maschinen. Selenium Grid leitet Befehle an Browser auf entfernten Maschinen weiter; laut offiziellem Dokument ist sein Zweck, Tests auf mehreren Maschinen parallel auszuführen. Eine Matrix „Edge unter Windows, Safari unter macOS, Firefox unter Linux" aus einer Suite laufen zu lassen, ist die Aufgabe von Grid. Playwright hat dafür keine direkte Entsprechung: Die Verteilung über Maschinen überlässt es Ihrem CI-System. Die Anbindung an Grid ist in seiner Dokumentation als experimentell gekennzeichnet und umfasst nur Chromium-basierte Browser.

Werkzeuge zur Fehlersuche

Unter dieser Überschrift liegt Playwright deutlich vorn. Eine Aufzeichnung, die mit context.tracing.start(screenshots=True, snapshots=True) beginnt und mit tracing.stop(path="trace.zip") endet, öffnet sich mit dem Befehl playwright show-trace trace.zip: Die DOM-Ansicht vor und nach jeder Aktion, die Netzwerkanfragen und die Konsolenmeldungen stehen auf einer Zeitachse. Warum ein nachts gelaufener Durchlauf leer zurückkam, beantworten Sie morgens aus dieser Datei. PWDEBUG=1 öffnet den Inspector und führt das Skript Schritt für Schritt aus, playwright codegen übersetzt Ihre Handlungen im Browser in Code.

In Selenium gibt es kein einzelnes gleichwertiges Werkzeug. Mit driver.save_screenshot() machen Sie ein Bildschirmfoto, in Chrome schalten Sie die Fähigkeit goog:loggingPrefs ein und lesen mit driver.get_log("browser") die Konsolenmeldungen; beides haben wir versucht, es funktioniert. Den Bedarf nach Aufzeichnen und Abspielen deckt die Erweiterung Selenium IDE. Das Mithören von Netzwerkanfragen kommt mit BiDi, doch für eine Aufzeichnung, die man später durchgeht, stützen Sie sich auf Reporting-Frameworks.

Tempo: Warum wir keine Zahlen nennen

Die meisten Vergleiche im Netz tragen eine Prozentangabe der Art „Playwright ist so viel schneller"; diese Zahlen entstanden auf der Maschine und auf der Seite des jeweiligen Autors. Die Architektur weckt eine Erwartung zugunsten von Playwright: eine offene Verbindung statt einer HTTP-Anfrage pro Befehl, ein Context statt eines Browsers. Doch bei einem echten Durchlauf über einen Proxy vergeht der größte Teil der Zeit im Netz und in der Antwortzeit der Zielseite; in unserem Beispiel endeten beide Skripte im Schatten der zehn Sekunden Seitenverzögerung.

Wenn Sie messen wollen, messen Sie auf Ihrem eigenen Ziel, mit demselben Proxy und derselben Nebenläufigkeit, an einer Stichprobe von einigen Dutzend Seiten. In den meisten Projekten kommt der eigentliche Gewinn nicht aus dem Werkzeugwechsel, sondern daraus, den Browser gar nicht erst unnötig zu öffnen.

Einsatzbereiche

  • Daten von dynamischen Seiten holen: In einem neuen Projekt senken das Mithören von Anfragen und das Blockieren von Ressourcen in Playwright den Verkehr; der allgemeine Aufbau steht auf der Seite Lösung zur Datenerhebung.
  • Viele Seiten regelmäßig durchlaufen: Warteschlange und Entdeckungslogik hängen nicht am Werkzeug; sehen Sie die Seite Web-Crawler-Lösung und den Beitrag Was ist Pagination und wie durchläuft man sie beim Scraping?.
  • Die eigene Anwendung aus verschiedenen Ländern testen: in Playwright ein Context pro Land, in Selenium eine Sitzung pro Land; das Detail steht auf der Seite Anwendungstest.
  • Kompatibilitätstest über Browser hinweg: Brauchen Sie echtes Safari und eine Betriebssystem-Matrix, dann Selenium und Grid.
  • Massenhaftes Durchlaufen unabhängiger Seiten: In beiden Werkzeugen genügt mit Rotierender Proxy eine einzige Gateway-Adresse; die Rotation übernimmt das Gateway.

Welches Werkzeug es auch wird, der Rahmen bleibt gleich: Halten Sie sich an die Regeln aus robots.txt und an die Nutzungsbedingungen, nutzen Sie die offizielle API, wenn es eine gibt, und halten Sie das Anfragetempo auf einem Niveau, das die Website trägt. Das Detail steht in Was ist robots.txt und wie liest man die Datei?.

Häufige Fehler

  • In Selenium die Zugangsdaten in die Proxy-Adresse einbetten. Chrome verwendet sie nicht; in unserem Versuch war das Ergebnis entweder eine Fehlerseite oder eine direkte Verbindung ohne Proxy.
  • Annehmen, die Seite sei geöffnet, weil driver.get() keinen Fehler warf. Selenium gibt den Statuscode nicht heraus; prüfen Sie das erwartete Element und die Ausgangs-IP.
  • Glauben, count() oder all() würden in Playwright warten. Sie warten nicht; zuerst first.wait_for().
  • Das Warten mit time.sleep() lösen. Das ist langsam und zugleich brüchig; nutzen Sie in Selenium WebDriverWait und in Playwright das Warten des Locators.
  • In Selenium implizites und explizites Warten mischen. Das offizielle Dokument warnt davor: Die Zeiten werden unvorhersehbar.
  • In Selenium driver.quit() nicht aufrufen. Jede nicht geschlossene Sitzung hinterlässt einen Chrome- und einen Treiberprozess; nutzen Sie try/finally.
  • Eine laufende Selenium-Suite nur der Mode wegen umziehen. Die Kosten des Wechsels liegen nicht bei den Selektoren, sondern bei der Wartelogik und der Testinfrastruktur.
  • Playwright aktualisieren, die Browser aber nicht. Jede Version will ihren eigenen Build; nehmen Sie einen Schritt playwright install in Ihr CI-Image auf.

Entscheidungshilfe

BedarfEmpfehlung
Neu startendes Scraping-Projekt in Python oder Node.jsPlaywright
Proxy mit Benutzername und PasswortPlaywright; in Selenium auf die IP-Whitelist wechseln
Dutzende unabhängige Sitzungen auf einer Maschine, pro Sitzung eine eigene IPPlaywright, Proxy pro Context
Laufende, gepflegte Selenium-TestsuiteBei Selenium bleiben
Testteam im Unternehmen mit Java- oder C#-SchwerpunktBeides geht; vorhandenes Framework und Erfahrung entscheiden
RubySelenium
Test in echtem Safari und auf verschiedenen BetriebssystemenSelenium und Grid
Nachträgliche Fehlersuche bei nachts laufenden JobsPlaywright, Trace Viewer
Netzwerkantwort lesen, Bilder und Fonts blockierenPlaywright (eingebaut)
Daten im Quelltext der Seite oder an einem JSON-EndpunktKeines von beiden: einfacher HTTP-Client oder Scrapy

Häufige Fragen

Ersetzt Playwright Selenium?

In neuen Projekten ist es oft die erste Wahl, aber zu sagen, es habe Selenium ersetzt, wäre nicht richtig. Selenium ist die Referenzumsetzung eines W3C-Standards, seine Treiber schreiben die Browserhersteller, und die fehlende bidirektionale Kommunikation wird über den Standard mit WebDriver BiDi ergänzt. Beide Projekte werden aktiv weiterentwickelt.

Ist der Wechsel von Selenium zu Playwright schwer?

Selektoren lassen sich größtenteils übernehmen; CSS und XPath funktionieren in beiden. Aufwand macht die Wartelogik: WebDriverWait-Blöcke fallen weg, an ihre Stelle tritt ein Locator-basierter Ablauf; auf der Testseite werden auch Page Objects, Reporting und CI-Schritte neu aufgesetzt. Ein kleines Skript zieht an einem Tag um; bei einer Suite mit Hunderten von Szenarien ist es weniger riskant, zuerst die neuen Szenarien in Playwright zu schreiben und die alten stehen zu lassen.

Lassen sich beide im selben Projekt nutzen?

Ja, sie kommen einander nicht ins Gehege. Üblich ist, die vorhandene Selenium-Regressionssuite zu behalten und neue Arbeiten in Playwright zu schreiben. Zu beachten ist, zwei getrennte Modelle der Browser-Einrichtung gemeinsam im CI-Image zu verwalten.

Lässt sich in Selenium überhaupt kein Proxy mit Benutzername und Passwort nutzen?

Auf dem Standardweg nicht: In der Proxy-Definition des WebDriver gibt es kein Feld für Zugangsdaten, und Chrome verwendet die in der Adresse eingebetteten Daten nicht. Pakete von Dritten, die einen lokalen Weiterleitungs-Proxy dazwischensetzen, füllen diese Lücke, bringen aber eine zusätzliche Abhängigkeit. Arbeiten Sie von einem Server mit fester IP, ist die IP-Whitelist einfacher und sicherer; das Passwort steht dann gar nicht im Code.

Ist Selenium in Python langsamer als Playwright?

Eine allgemeine Antwort gibt es nicht. Die Architektur spricht für Playwright, doch bei einem Durchlauf über einen Proxy bestimmen meist das Netz und die Zielseite die Zeit. Übertragen Sie veröffentlichte Prozentzahlen nicht auf Ihre eigene Arbeit; messen Sie am selben Ziel, mit demselben Proxy und derselben Nebenläufigkeit, selbst.

Verhalten sich beide im Headless-Modus anders?

Beide laufen ohne Fenster. Playwright startet standardmäßig headless und lädt dafür einen eigenen „Headless Shell"-Build herunter; um das Fenster zu sehen, schreiben Sie launch(headless=False). Selenium startet standardmäßig mit Fenster und wechselt in Chrome mit dem Argument --headless=new in den fensterlosen Modus. Die Proxy-Einstellung ist in beiden Modi dieselbe.

Fazit

Playwright und Selenium erledigen dieselbe Arbeit auf verschiedenen Wegen. Selenium schickt Befehle über W3C WebDriver an den Treiber des Browserherstellers; es deckt mehr Sprachen, echtes Safari und mit Grid die Verteilung über Maschinen ab und überlässt Ihnen das Warten und die Proxy-Zugangsdaten. Playwright baut eine dauerhafte Verbindung zum Browser auf; es wartet von selbst, nimmt den Proxy mit Benutzername und Passwort pro Context, hört den Netzwerkverkehr mit und erleichtert die Fehlersuche mit einer Trace-Datei. In einem neuen Scraping-Projekt bringt Playwright Sie mit weniger Code voran; haben Sie eine laufende Selenium-Suite, genügt es meist, sie über eine IP-Whitelist an den Proxy zu binden. Die Proxy-Arten, die Sie mit beiden Werkzeugen nutzen können, finden Sie in unseren Proxy-Diensten.

ChatGPT fragenClaude fragen