Automação Web com Selenium e Python — 2026 | Python Brasil
Aprenda automação web com Selenium e Python: instalação, localizadores, formulários, esperas, web scraping de sites dinâmicos, anti-bot e boas práticas.
O Selenium é a ferramenta mais popular para automação de navegadores web. Com Python e Selenium, você pode automatizar testes, preencher formulários, extrair dados de sites dinâmicos e muito mais. Neste guia, você vai aprender desde a configuração até técnicas avançadas de automação — incluindo quando o Selenium é a escolha certa e quando vale a pena trocar por outras ferramentas.
Se o seu objetivo é só ler páginas estáticas, um cliente HTTP simples costuma bastar — confira nosso comparativo do HTTPX como alternativa moderna ao requests. O Selenium entra em cena quando a página depende de JavaScript para renderizar o conteúdo.
Por que usar Selenium?
O Selenium controla um navegador real (Chrome, Firefox, Edge), executando JavaScript e interagindo com a página como um usuário faria. Isso resolve três problemas comuns:
- Conteúdo renderizado por JavaScript — SPAs (React, Vue, Angular) e sites com carregamento dinâmico.
- Interação autêntica — cliques, preenchimento de formulários, navegação por abas.
- Testes end-to-end — validar fluxos completos da aplicação no navegador.
A contrapartida é o custo: abrir um navegador é lento e consome muita memória. Por isso, a regra prática é usar a ferramenta mais leve que resolve o problema.
Selenium, Playwright ou requests + BeautifulSoup?
| Cenário | Ferramenta recomendada |
|---|---|
| Página HTML estática, sem JS | requests + BeautifulSoup (veja o tutorial de web scraping) |
| Página com JS, pouca interação | Playwright ou Selenium em modo headless |
| Fluxo com login, cliques e formulários | Selenium ou Playwright |
| Extração em larga escala com IA | pipelines com scraping com IA |
O Playwright é a alternativa moderna da Microsoft, com API mais rápida e auto-wait nativo. O Selenium continua vencedor em ecossistema maduro, documentação e compatibilidade com navegadores legados — além de ser o padrão em muitas vagas de QA, tema que aprofundamos no artigo sobre carreira em QA e automação de testes.
Instalação e Configuração
Instale o Selenium e o gerenciador de drivers:
pip install selenium webdriver-manager
A partir do Selenium 4.6, o próprio Selenium já baixa o driver correto automaticamente (Selenium Manager), então o webdriver-manager é opcional. Recomendamos manter um ambiente virtual isolado para evitar conflitos de versão.
Primeiro Script de Automação
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Configurar o navegador
options = Options()
# options.add_argument("--headless=new") # Sem interface gráfica
options.add_argument("--no-sandbox")
options.add_argument("--window-size=1920,1080")
# Criar instância do navegador (driver é baixado automaticamente)
driver = webdriver.Chrome(options=options)
try:
# Navegar para um site
driver.get("https://www.python.org")
# Obter informações da página
print(f"Título: {driver.title}")
print(f"URL: {driver.current_url}")
finally:
# Sempre feche o navegador
driver.quit()
Localizando Elementos
O Selenium oferece diversas formas de encontrar elementos na página:
from selenium.webdriver.common.by import By
# Por ID
elemento = driver.find_element(By.ID, "meu-id")
# Por nome
elemento = driver.find_element(By.NAME, "email")
# Por classe CSS
elementos = driver.find_elements(By.CLASS_NAME, "item")
# Por seletor CSS (mais flexível)
elemento = driver.find_element(By.CSS_SELECTOR, "div.container > h1")
elemento = driver.find_element(By.CSS_SELECTOR, "input[type='email']")
# Por XPath (mais poderoso)
elemento = driver.find_element(By.XPATH, "//button[@type='submit']")
elementos = driver.find_elements(By.XPATH, "//div[@class='produto']//span[@class='preco']")
# Por texto do link
elemento = driver.find_element(By.LINK_TEXT, "Saiba mais")
elemento = driver.find_element(By.PARTIAL_LINK_TEXT, "Saiba")
# Por tag HTML
elementos = driver.find_elements(By.TAG_NAME, "li")
Prefira seletores CSS ou ByID sempre que possível — eles são mais rápidos e legíveis que XPath. Reserve XPath para buscas que dependem da estrutura ou do texto do elemento.
Interagindo com Formulários
Automatizar formulários é um dos usos mais comuns:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
def preencher_formulario(driver):
"""Exemplo de preenchimento automático de formulário."""
driver.get("https://exemplo.com/cadastro")
# Preencher campo de texto
campo_nome = driver.find_element(By.NAME, "nome")
campo_nome.clear() # Limpar campo antes de digitar
campo_nome.send_keys("Ana Silva")
# Preencher email
campo_email = driver.find_element(By.NAME, "email")
campo_email.clear()
campo_email.send_keys("[email protected]")
# Selecionar opção em dropdown
dropdown = Select(driver.find_element(By.NAME, "estado"))
dropdown.select_by_visible_text("São Paulo")
# ou: dropdown.select_by_value("SP")
# ou: dropdown.select_by_index(25)
# Marcar checkbox
checkbox = driver.find_element(By.ID, "aceito-termos")
if not checkbox.is_selected():
checkbox.click()
# Selecionar radio button
radio = driver.find_element(By.CSS_SELECTOR, "input[value='plano-pro']")
radio.click()
# Clicar no botão de enviar
botao = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
botao.click()
Esperas: Explícitas vs Implícitas
Sites dinâmicos carregam elementos de forma assíncrona. Esperas são essenciais para evitar erros de “elemento não encontrado”:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
# Espera implícita (aplica a todos os find_element)
driver.implicitly_wait(10) # Espera até 10 segundos
# Espera explícita (recomendada — mais precisa)
wait = WebDriverWait(driver, 10)
try:
# Esperar elemento ficar visível
elemento = wait.until(
EC.visibility_of_element_located((By.ID, "resultado"))
)
print(f"Texto: {elemento.text}")
# Esperar elemento ser clicável
botao = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, ".btn-continuar"))
)
botao.click()
# Esperar texto específico aparecer
wait.until(
EC.text_to_be_present_in_element(
(By.ID, "status"), "Concluído"
)
)
# Esperar elemento desaparecer (loading spinner)
wait.until(
EC.invisibility_of_element_located((By.CLASS_NAME, "spinner"))
)
except TimeoutException:
print("Timeout: elemento não encontrado no tempo limite")
A regra de ouro: prefira esperas explícitas com condições claras. A espera implícita é um “band-aid” global que pode mascarar problemas de performance e dificultar o diagnóstico.
Web Scraping de Sites Dinâmicos
O Selenium é ideal para extrair dados de sites que usam JavaScript. Combine-o com clientes HTTP assíncronos quando precisar buscar múltiplas URLs em paralelo.
import json
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def extrair_produtos(driver, url):
"""Extrai dados de produtos de uma página dinâmica."""
driver.get(url)
# Esperar produtos carregarem
wait = WebDriverWait(driver, 15)
wait.until(
EC.presence_of_all_elements_located((By.CLASS_NAME, "produto-card"))
)
# Scroll para carregar mais itens (infinite scroll)
ultimo_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
novo_height = driver.execute_script("return document.body.scrollHeight")
if novo_height == ultimo_height:
break
ultimo_height = novo_height
# Extrair dados
produtos = []
cards = driver.find_elements(By.CLASS_NAME, "produto-card")
for card in cards:
nome = card.find_element(By.CLASS_NAME, "nome").text
preco = card.find_element(By.CLASS_NAME, "preco").text
produtos.append({"nome": nome, "preco": preco})
return produtos
# Salvar dados extraídos
# produtos = extrair_produtos(driver, "https://loja.exemplo.com/produtos")
# with open("produtos.json", "w", encoding="utf-8") as f:
# json.dump(produtos, f, indent=2, ensure_ascii=False)
Evitando Bloqueios: Scraping Ético e Robusto
Sites modernos detectam automação. Para construir scrapers que funcionam e respeitam os servidores, siga estas práticas:
- Respeite
robots.txte os Termos de Serviço do site. Nem tudo que é tecnicamente possível é permitido. - Defina um user-agent realista e identifique-se quando apropriado.
- Aplique delays entre requisições —
time.sleepaleatório evita sobrecarregar o servidor e reduz a chance de bloqueio. - Use proxies residenciais com responsabilidade quando a infraestrutura exigir, respeitando os limites do serviço contratado.
- Prefira APIs oficiais sempre que existirem; são mais estáveis e legais que raspagem.
Para operações em produção, considere ferramentas como o undetected-chromedriver, que reduz a detecção automatizada. Em qualquer caso, automação web não é licença para extrair dados pessoais ou violar propriedade intelectual.
Executando em Paralelo
Quando você precisa processar muitas páginas, abrir um único navegador vira um gargalo. Existem duas estratégias principais:
- Paralelismo na própria aplicação — instancie vários drivers com
concurrent.futures(threads) ou filas assíncronas. Cada driver mantém sua própria sessão. - Selenium Grid — um servidor central orquestra múltiplos nós (máquinas/navegadores), ideal para suítes de testes em CI/CD.
Para suítes de testes, o ecossistema Python oferece integração direta do Selenium com o pytest, permitindo fixtures que sobem um driver por teste de forma isolada e paralelizável.
Executando JavaScript
Você pode executar JavaScript diretamente no navegador:
# Executar JavaScript simples
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Obter valor de elemento via JavaScript
titulo = driver.execute_script("return document.title;")
# Modificar atributos de elementos
driver.execute_script(
"arguments[0].setAttribute('value', 'novo valor');",
driver.find_element(By.ID, "campo")
)
# Remover overlay ou popup
driver.execute_script("""
var overlay = document.querySelector('.modal-overlay');
if (overlay) overlay.remove();
""")
Capturas de Tela
Útil para debug e documentação:
# Screenshot da página inteira
driver.save_screenshot("pagina_completa.png")
# Screenshot de um elemento específico
elemento = driver.find_element(By.ID, "grafico")
elemento.screenshot("grafico.png")
Gerenciando Abas e Janelas
# Abrir nova aba
driver.execute_script("window.open('https://python.org', '_blank');")
# Alternar entre abas
abas = driver.window_handles
driver.switch_to.window(abas[1]) # Ir para segunda aba
print(f"Aba atual: {driver.title}")
driver.switch_to.window(abas[0]) # Voltar para primeira aba
# Fechar aba atual
driver.close()
Modo Headless para Servidores
Para execução em servidores sem interface gráfica:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1920,1080")
# User agent para evitar detecção
options.add_argument(
"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
)
driver = webdriver.Chrome(options=options)
Em containers Docker, o argumento --disable-dev-shm-usage é indispensável: sem ele, o Chrome esgota o /dev/shm compartilhado e trava.
Erros Comuns e Como Resolver
| Erro | Causa típica | Solução |
|---|---|---|
NoSuchElementException | Elemento ainda não carregou ou seletor errado | Use espera explícita; confira o seletor no DevTools |
TimeoutException | Condição de espera não atendida no prazo | Aumente o tempo ou mude a condição; verifique se há overlay bloqueando |
StaleElementReferenceException | Elemento foi re-renderizado após ser localizado | Re-localize o elemento antes de interagir |
ElementNotInteractableException | Elemento fora da viewport ou oculto | Role até o elemento com .scroll_into_view() ou use EC.element_to_be_clickable |
SessionNotCreatedException | Versão do driver incompatível com o navegador | Atualize o Selenium ou use o Selenium Manager |
Tratar exceções específicas — em vez de um genérico except Exception — deixa o diagnóstico muito mais rápido.
Classe de Automação Reutilizável
Para projetos maiores, encapsule a lógica em uma classe usando o padrão Page Object:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class PaginaLogin:
"""Page Object para a página de login."""
URL = "https://app.exemplo.com/login"
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10)
def abrir(self):
self.driver.get(self.URL)
return self
def preencher_email(self, email):
campo = self.wait.until(
EC.visibility_of_element_located((By.NAME, "email"))
)
campo.clear()
campo.send_keys(email)
return self
def preencher_senha(self, senha):
campo = self.driver.find_element(By.NAME, "senha")
campo.clear()
campo.send_keys(senha)
return self
def clicar_entrar(self):
botao = self.wait.until(
EC.element_to_be_clickable((By.ID, "btn-login"))
)
botao.click()
return self
def login(self, email, senha):
"""Realiza login completo."""
self.abrir()
self.preencher_email(email)
self.preencher_senha(senha)
self.clicar_entrar()
return self
O padrão Page Object isola a estrutura da página do fluxo de teste: quando o HTML muda, você atualiza um só lugar. Para escalar a suíte de testes, combine Page Objects com testes unitários em Python e fixtures do pytest.
Boas Práticas
Ao usar Selenium com Python, siga estas recomendações:
- Sempre use esperas explícitas ao invés de
time.sleep(exceto em loops de scroll, onde um pequeno delay é aceitável). - Feche o navegador em um bloco
finallyou use context managers. - Use o padrão Page Object para manter o código organizado.
- Respeite os termos de serviço dos sites que você acessa.
- Adicione delays razoáveis entre ações para não sobrecarregar servidores.
- Use modo headless para execução em CI/CD e servidores.
- Trate exceções específicas do Selenium para mensagens de erro claras.
- Rode os navegadores em containers (Docker) para resultados reproduzíveis.
Conclusão
Selenium com Python é uma combinação poderosa para automação web. Desde testes automatizados até web scraping de sites dinâmicos, as possibilidades são vastas. Comece com scripts simples, domine as esperas explícitas e evolua para o padrão Page Object conforme seus projetos crescem. Lembre-se de sempre usar a automação de forma ética e respeitando os termos de uso dos sites — quando existir uma API oficial, como nas de serviços REST com FastAPI, ela quase sempre será a escolha mais robusta.
Testes e automação em outras linguagens: Kotlin é muito usado para testes automatizados no ecossistema Android e web com frameworks como Kotest. Go com chromedp oferece automação headless nativa sem depender do Selenium, usando o Chrome DevTools Protocol diretamente.
Equipe Python Brasil
Contribuidor do Python Brasil — Aprenda Python em Português