Playwright: web scraping & testen

Meester browser automatisering voor testen & scrapen

Inhoud

Playwright is een krachtig, moderne browserautomatiseringsframework dat web scraping en eind- tot-eind-testen revolutioneert.

Ontwikkeld door Microsoft, biedt het een geïntegreerde API voor het automatiseren van Chromium, Firefox en WebKit-browsers met ongekende betrouwbaarheid en snelheid.

playwright ui

Wat is Playwright?

Playwright is een open-source browserautomatiseringsframework dat ontwikkelaars in staat stelt om betrouwbare eind- tot-eind-tests te schrijven en geavanceerde oplossingen voor web scraping te bouwen. In tegenstelling tot traditionele automatiseringsgereedschappen is Playwright vanaf het begin ontworpen om moderne webtoepassingen met dynamische inhoud, single-page applications (SPAs) en complexe JavaScript-frameworks te hanteren.

Het framework lost het kernprobleem op dat vorige automatiseringsgereedschappen plagen: onbetrouwbaarheid. Playwright introduceert automatische wachttijden die automatisch wachten tot elementen actievereedzaam zijn voordat er acties worden uitgevoerd, wat de noodzaak van willekeurige time-outs en sleep-statements elimineert die tests onbetrouwbaar maken.

Belangrijke kenmerken

Cross-browser ondersteuning: Playwright ondersteunt alle belangrijke browserengines - Chromium (inclusief Chrome en Edge), Firefox en WebKit (Safari). Dit betekent dat je je automatiseringscript één keer kunt schrijven en het overal kunt uitvoeren zonder aanpassingen, waardoor je webtoepassingen consistent werken op elk platform.

Automatische wachttijden: Een van de krachtigste functies van Playwright is zijn ingebouwde automatische wachttijden. Voordat er een actie wordt uitgevoerd, wacht Playwright automatisch tot elementen zichtbaar, ingeschakeld, stabiel en niet belemmerd zijn. Dit elimineert race conditions en maakt tests aanzienlijk betrouwbaarder in vergelijking met gereedschappen zoals Selenium waarbij expliciete wachttijden vaak nodig zijn.

Netwerkinterceptie: Playwright stelt je in staat om netwerkverzoeken en -reacties te intercepteren, te wijzigen en te vervalsen. Dit is onmisbaar voor het testen van randgevallen, het simuleren van traag netwerkverkeer, het blokkeren van onnodige bronnen tijdens het scraping en het vervalsen van API-antwoorden zonder backend.

Mobiele emulatie: Test mobiele webtoepassingen door verschillende mobiele apparaten te emuleren met specifieke viewportgrootte, gebruikersagenten en touchgebeurtenissen. Playwright bevat apparaatbeschrijvingen voor populaire telefoons en tabletten.

Mogelijke selectoren: Boven en naast CSS- en XPath-selectoren ondersteunt Playwright tekstselectoren, rolgebaseerde selectoren voor toegankelijkheidstesten en zelfs experimentele React- en Vue-selectoren voor componentgebaseerde frameworks.

Installatie en opzet

Het instellen van Playwright is eenvoudig over verschillende programmeertalen.

Python-installatie

Voor Python-projecten kan Playwright geïnstalleerd worden via pip en bevat zowel synchrone als asynchrone API’s. Als je op zoek bent naar een snellere, modernere Python-pakketbeheerder, raad onze gids aan over uv - Python-pakket, project- en omgevingsbeheerder:

# Installeer Playwright-pakket
pip install playwright

# Installeer browsers (Chromium, Firefox, WebKit)
playwright install

# Voor specifieke browser alleen
playwright install chromium

Voor een uitgebreid overzicht van Python-syntaxis en veelgebruikte opdrachten terwijl je werkt met Playwright, verwijzen we naar onze Python Cheat Sheet.

JavaScript/TypeScript-installatie

Voor Node.js-projecten, installeer Playwright via npm of yarn:

# Gebruik npm
npm init playwright@latest

# Gebruik yarn
yarn create playwright

# Manuele installatie
npm install -D @playwright/test
npx playwright install

De opdracht npm init playwright biedt een interactieve opzet die je project configureert met voorbeeldtests, configuratiebestanden en GitHub Actions-werkstroom.

Basisconfiguratie

Maak een playwright.config.ts (TypeScript) of playwright.config.js (JavaScript) bestand:

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  timeout: 30000,
  retries: 2,
  workers: 4,
  use: {
    headless: true,
    viewport: { width: 1280, height: 720 },
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Web scraping met Playwright

Playwright is uitstekend voor web scraping, vooral voor moderne websites met dynamische inhoud die traditionele scrapingbibliotheken moeilijk maken.

Basisvoorbeeld voor scraping

Hieronder volgt een uitgebreid Python-voorbeeld dat kernconcepten van scraping demonstreert:

from playwright.sync_api import sync_playwright
import json

def scrape_website():
    with sync_playwright() as p:
        # Start browser
        browser = p.chromium.launch(headless=True)
        
        # Create context for isolation
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
        )
        
        # Open new page
        page = context.new_page()
        
        # Navigate to URL
        page.goto('https://example.com/products')
        
        # Wait for content to load
        page.wait_for_selector('.product-item')
        
        # Extract data
        products = page.query_selector_all('.product-item')
        
        data = []
        for product in products:
            title = product.query_selector('h2').inner_text()
            price = product.query_selector('.price').inner_text()
            url = product.query_selector('a').get_attribute('href')
            
            data.append({
                'title': title,
                'price': price,
                'url': url
            })
        
        # Clean up
        browser.close()
        
        return data

# Run scraper
results = scrape_website()
print(json.dumps(results, indent=2))

Het afhandelen van dynamische inhoud

Moderne websites laden vaak inhoud dynamisch via JavaScript. Playwright verwerkt dit soepel:

async def scrape_dynamic_content():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        
        await page.goto('https://example.com/infinite-scroll')
        
        # Scroll to load more content
        for _ in range(5):
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
            await page.wait_for_timeout(2000)
        
        # Wait for network to be idle
        await page.wait_for_load_state('networkidle')
        
        # Extract all loaded items
        items = await page.query_selector_all('.item')
        
        await browser.close()

Het converteren van gescrapte inhoud naar Markdown

Na het extraheren van HTML-inhoud met Playwright, heb je vaak behoefte aan het converteren naar een bruikbaardere vorm. Voor uitgebreide gidsen over het converteren van HTML naar Markdown, zie onze artikelen over HTML naar Markdown converteren met Python: Een uitgebreide gids die 6 verschillende Python-bibliotheken vergelijkt, en HTML-inhoud converteren naar Markdown met LLM en Ollama voor AI-gestuurde conversie. Als je werkt met Word-documenten in plaats daarvan, zie onze gids over Word-documenten converteren naar Markdown.

Authenticatie en sessiebeheer

Wanneer scraping authenticatie vereist, maakt Playwright het eenvoudig om de browserstatus op te slaan en opnieuw te gebruiken:

def login_and_save_session():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()
        page = context.new_page()
        
        # Login
        page.goto('https://example.com/login')
        page.fill('input[name="username"]', 'your_username')
        page.fill('input[name="password"]', 'your_password')
        page.click('button[type="submit"]')
        
        # Wait for navigation after login
        page.wait_for_url('**/dashboard')
        
        # Save authenticated state
        context.storage_state(path='auth_state.json')
        
        browser.close()

def scrape_with_saved_session():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        # Reuse saved authentication state
        context = browser.new_context(storage_state='auth_state.json')
        page = context.new_page()
        
        # Already authenticated!
        page.goto('https://example.com/protected-data')
        # ... scrape protected content
        
        browser.close()

Deze aanpak is vooral handig wanneer je werkt met APIs of MCP-servers voor AI-integraties. Voor een complete gids over het implementeren van web scraping in AI-hulpmiddelen, zie ons artikel over MCP-servers bouwen in Python: WebSearch & Scrape.

Eind- tot-eind-testen

De primaire toepassing van Playwright is het schrijven van robuuste eind- tot-eind-tests voor webtoepassingen.

Je eerste test schrijven

Hieronder volgt een volledig testvoorbeeld in TypeScript:

import { test, expect } from '@playwright/test';

test('user can add item to cart', async ({ page }) => {
  // Navigate to homepage
  await page.goto('https://example-shop.com');
  
  // Search for product
  await page.fill('[data-testid="search-input"]', 'laptop');
  await page.press('[data-testid="search-input"]', 'Enter');
  
  // Wait for search results
  await expect(page.locator('.product-card')).toBeVisible();
  
  // Click first product
  await page.locator('.product-card').first().click();
  
  // Verify product page loaded
  await expect(page).toHaveURL(/\/product\/.+/);
  
  // Add to cart
  await page.click('[data-testid="add-to-cart"]');
  
  // Verify cart updated
  const cartCount = page.locator('[data-testid="cart-count"]');
  await expect(cartCount).toHaveText('1');
});

Page Object Model

Voor grotere testuitvoeringen, gebruik het Page Object Model patroon om de onderhoudbaarheid te verbeteren:

// pages/LoginPage.ts
export class LoginPage {
  constructor(private page: Page) {}
  
  async navigate() {
    await this.page.goto('/login');
  }
  
  async login(username: string, password: string) {
    await this.page.fill('[name="username"]', username);
    await this.page.fill('[name="password"]', password);
    await this.page.click('button[type="submit"]');
  }
  
  async getErrorMessage() {
    return await this.page.locator('.error-message').textContent();
  }
}

// tests/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';

test('login with invalid credentials shows error', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.navigate();
  await loginPage.login('invalid@email.com', 'wrongpass');
  
  const error = await loginPage.getErrorMessage();
  expect(error).toContain('Invalid credentials');
});

Geavanceerde functies

Codegen - Automatische testgeneratie

Het Codegen-hulpmiddel van Playwright genereert tests door interacties met een webpagina op te nemen:

# Open Codegen
playwright codegen example.com

# Met specifieke browser
playwright codegen --browser firefox example.com

# Met opgeslagen authenticatiestatus
playwright codegen --load-storage=auth.json example.com

Terwijl je met de pagina interactieert, genereert Codegen code in real-time. Dit is zeer handig voor het snel prototyperen van tests of het leren van Playwrights selector-syntaxis.

Trace Viewer voor het debuggen

Wanneer tests falen, kan het lastig zijn om te begrijpen waarom. De Trace Viewer van Playwright biedt een tijdslijnweergave van de testuitvoering:

// Trace inschakelen in configuratie
use: {
  trace: 'on-first-retry',
}

Na een gefaalde test en herprobeer, bekijk de trace:

playwright show-trace trace.zip

De Trace Viewer toont screenshots bij elke actie, netwerkactiviteit, consolelogboeken en DOM-snapshotten, waardoor het debuggen eenvoudig is.

Netwerkinterceptie en vervalsing

Intercepteer en wijzig netwerkverkeer voor het testen van randgevallen:

def test_with_mocked_api():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        
        # Vervals API-antwoord
        def handle_route(route):
            if 'api/products' in route.request.url:
                route.fulfill(
                    status=200,
                    body=json.dumps({
                        'products': [
                            {'id': 1, 'name': 'Test Product', 'price': 99.99}
                        ]
                    })
                )
            else:
                route.continue_()
        
        page.route('**/*', handle_route)
        
        page.goto('https://example.com')
        # Pagina gebruikt nu gemockte gegevens
        
        browser.close()

Mobiel testen

Test je responsieve ontwerpen op verschillende apparaten:

from playwright.sync_api import sync_playwright

def test_mobile():
    with sync_playwright() as p:
        # Gebruik apparaatbeschrijving
        iphone_13 = p.devices['iPhone 13']
        
        browser = p.webkit.launch()
        context = browser.new_context(**iphone_13)
        page = context.new_page()
        
        page.goto('https://example.com')
        
        # Interactie als mobiele gebruiker
        page.locator('#mobile-menu-button').click()
        
        browser.close()

Best practices

Voor web scraping

  1. Gebruik headless-modus in productie: Headless-browsing is sneller en gebruikt minder resources
  2. Implementeer rate limiting: Respecteer doelwebsites met vertragingen tussen aanvragen
  3. Behandel fouten op een elegante manier: Netwerkproblemen, time-outs en wijzigingen in selectoren gebeuren
  4. Wissel gebruikersagenten: Vermijd detectie door variabele browser-vingerafdrukken
  5. Respecteer robots.txt: Controleer en volg website-scrapingbeleid
  6. Gebruik contextisolatie: Maak afzonderlijke browsercontexten voor parallele scraping

Wanneer gescrapte inhoud omgezet moet worden naar markdownformaat, overweeg dan gebruik te maken van LLM-gestuurde conversietools of Python-bibliotheken gespecialiseerd in HTML-naar-Markdown-conversie voor schoner output.

Voor testen

  1. Gebruik data-testid-attributen: Stabielere dan CSS-classes die vaak veranderen
  2. Vermijd harde wachten: Gebruik de ingebouwde wachttijden van Playwright in plaats van sleep()
  3. Houd tests onafhankelijk: Elke test moet in isolatie kunnen worden uitgevoerd
  4. Gebruik fixtures: Delen setupcode efficiënt tussen tests
  5. Voer tests parallel uit: Maak gebruik van Playwrights workerthreads voor snelheid
  6. Registreer traces bij falen: Schakel trace-opname in voor eenvoudiger debuggen

Prestatieoptimalisatie

# Schakel onnodige resources uit
def fast_scraping():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        context = browser.new_context()
        page = context.new_page()
        
        # Blokkeer afbeeldingen en stylesheets om het scraping te versnellen
        async def block_resources(route):
            if route.request.resource_type in ['image', 'stylesheet', 'font']:
                await route.abort()
            else:
                await route.continue_()
        
        page.route('**/*', block_resources)
        page.goto('https://example.com')
        
        browser.close()

Vergelijking van Playwright met alternatieven

Playwright vs Selenium

Voordelen van Playwright:

  • Ingebouwde automatische wachttijden elimineren onbetrouwbaarheid van tests
  • Snel uitvoeren vanwege moderne architectuur
  • Betere netwerkinterceptie en vervalsing
  • Superieure debuggereedschappen (Trace Viewer)
  • Simpelere API met minder boilerplate
  • Meerdere browsers met enkele installatie

Voordelen van Selenium:

  • Meer rijpe ecosystem met uitgebreide gemeenschap
  • Ondersteunt meer programmeertalen
  • Breedere browsercompatibiliteit, inclusief oudere versies

Playwright vs Puppeteer

Voordelen van Playwright:

  • Echte cross-browserondersteuning (Firefox, WebKit, Chromium)
  • Betere API-ontwerp op basis van lessen van Puppeteer
  • Machtigere debuggereedschappen
  • Microsoft-backing en actieve ontwikkeling

Voordelen van Puppeteer:

  • Slechtere footprint
  • Expertise in Chrome DevTools Protocol

Voor de meeste nieuwe projecten is Playwright de aanbevolen keuze vanwege zijn moderne architectuur en uitgebreide functionaliteit. Als je met Go werkt in plaats van Python of JavaScript en web scrapingfunctionaliteiten nodig hebt, raad onze gids aan over Beautiful Soup Alternatieven voor Go voor vergelijkbare scrapinggereedschappen in het Go-ecosysteem.

Algemene toepassingsgebieden

Dataextractie voor AI/LLM-toepassingen

Playwright is uitstekend voor het verzamelen van trainingdata of het maken van webzoekfunctionaliteiten voor AI-modellen. Bij het bouwen van MCP (Model Context Protocol)-servers kan Playwright de web scrapingcomponent hanteren terwijl LLMs de geëxtraheerde inhoud verwerken.

Automatisering in CI/CD

Integreer Playwright-tests in je continue integratiepijplijn:

# .github/workflows/playwright.yml
name: Playwright Tests
on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
jobs:
  test:
    timeout-minuten: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 18
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
      run: npx playwright test
    - uses: actions/upload-artifact@v3
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

Website monitoring

Monitor je productiesites voor uptime en functionaliteit:

import schedule
import time

def monitor_website():
    with sync_playwright() as p:
        try:
            browser = p.chromium.launch()
            page = browser.new_page()
            page.goto('https://your-site.com', timeout=30000)
            
            # Check kritieke elementen
            assert page.is_visible('.header')
            assert page.is_visible('#main-content')
            
            print("✓ Website is gezond")
        except Exception as e:
            print(f"✗ Websiteprobleem gedetecteerd: {e}")
            # Stuur melding
        finally:
            browser.close()

# Run elke 5 minuten
schedule.every(5).minutes.do(monitor_website)

while True:
    schedule.run_pending()
    time.sleep(1)

Probleemoplossing voor veelvoorkomende problemen

Browserinstallatieproblemen

Als browsers niet kunnen worden gedownload:

# Stel aangepaste downloadlocatie in
PLAYWRIGHT_BROWSERS_PATH=/custom/path playwright install

# Wis cache en installeer opnieuw
playwright uninstall
playwright install

Time-outfouten

Verhoog time-outs voor traag netwerk of complexe pagina’s:

page.goto('https://slow-site.com', timeout=60000)  # 60 seconden
page.wait_for_selector('.element', timeout=30000)  # 30 seconden

Selector niet gevonden

Gebruik de Playwright-inspecteur om de juiste selectors te identificeren:

PWDEBUG=1 pytest test_file.py

Dit opent de inspecteur waar je met de muis over elementen kunt bewegen om hun selectors te zien.

Conclusie

Playwright vertegenwoordigt de toekomst van browserautomatiseringstechnologie, met krachtige functies en uitstekende ontwikkelaarservaring. Of je nu een web scrapingpijplijn bouwt, uitgebreide testdekking implementeert of automatiseringswerkstromen creëert, biedt Playwright de gereedschappen en betrouwbaarheid die je nodig hebt.

De automatische wachttijden elimineren onbetrouwbaarheid van tests, cross-browserondersteuning zorgt ervoor dat je toepassingen overal werken, en krachtige debuggereedschappen maken het oplossen van problemen eenvoudig. Aangezien webtoepassingen steeds complexer worden, maakt Playwrights moderne architectuur en actieve ontwikkeling het een uitstekende keuze voor elke browserautomatiseringsbehoeften.

Voor Python-ontwikkelaars die werken aan datapijplijnen of web scrapingprojecten, integreert Playwright zich soepel met moderne pakketbeheerders en werkt uitstekend samen met pandas, requests en andere data sciencegereedschappen. De mogelijkheid om gestructureerde data te extraheren van complexe moderne websites maakt het onmisbaar voor AI-toepassingen, onderzoeksprojecten en business intelligence. Wanneer gecombineerd met HTML-naar-Markdown-conversiegereedschappen en correcte inhoudsverwerking, wordt Playwright een complete oplossing voor het extraheren, transformeren en gebruiken van webdata op schaal.

Andere verwijzingen