Intermediário 10 min de leitura 10/08/2026

Web scraping com Playwright em Python: guia completo

Scraping de sites com JavaScript usando Playwright: paginação, login e coleta de dados

BeautifulSoup e Requests funcionam bem para páginas HTML estáticas. O problema é que a maioria dos sites modernos renderiza conteúdo com JavaScript — e aí elas não chegam nem perto. Playwright controla um navegador de verdade, então o que você vê no Chrome é exatamente o que você consegue coletar.

Instalação

pip install playwright
playwright install chromium

Estrutura básica

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://exemplo.com")
    print(page.title())
    browser.close()
Use headless=False durante o desenvolvimento para ver o navegador abrindo na tela — facilita muito o debug.

Selecionando elementos

Playwright usa seletores CSS e texto para localizar elementos:

# Por seletor CSS
titulo = page.locator("h1").inner_text()

# Por texto visível
page.get_by_text("Ver mais").click()

# Todos os itens de uma lista
itens = page.locator(".produto-card").all()
for item in itens:
    nome = item.locator(".nome").inner_text()
    preco = item.locator(".preco").inner_text()
    print(nome, preco)

Lidando com JavaScript e esperas

O maior erro de quem começa é não esperar o conteúdo carregar. Playwright tem esperas inteligentes:

# Espera o elemento aparecer antes de interagir
page.wait_for_selector(".resultados")

# Espera a rede ficar ociosa (útil após cliques que disparam requisições)
page.click("#carregar-mais")
page.wait_for_load_state("networkidle")

Exemplo real: coletando livros com paginação

import json
from playwright.sync_api import sync_playwright

def coletar_livros():
    livros = []

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto("https://books.toscrape.com")

        while True:
            cards = page.locator("article.product_pod").all()
            for card in cards:
                livros.append({
                    "titulo": card.locator("h3 a").get_attribute("title"),
                    "preco": card.locator(".price_color").inner_text(),
                })

            proximo = page.locator("li.next a")
            if proximo.count() == 0:
                break
            proximo.click()
            page.wait_for_load_state("networkidle")

        browser.close()

    return livros

dados = coletar_livros()
print(f"{len(dados)} livros coletados")

with open("livros.json", "w") as f:
    json.dump(dados, f, ensure_ascii=False, indent=2)

Fazendo login antes de coletar

page.goto("https://site.com/login")
page.fill("#email", "seu@email.com")
page.fill("#senha", "suasenha")
page.click("button[type=submit]")
page.wait_for_url("**/dashboard")

# Agora você está autenticado — pode navegar para páginas protegidas
page.goto("https://site.com/dados-privados")

Salvando o estado de login (evitar logar toda vez)

# Salva cookies e storage após login
page.context.storage_state(path="estado.json")

# Na próxima execução, reutiliza:
context = browser.new_context(storage_state="estado.json")

Próximos passos

Com os dados coletados, o próximo passo é limpá-los e analisá-los — e é exatamente isso que o tutorial de Pandas cobre.