brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
browser-automationUse quando o usuário pedir para automatizar tarefas no navegador, fazer scraping de sites, preencher formulários, capturar screenshots, extrair dados estruturados de páginas web ou construir workflows de automação web. NÃO para testes — use playwright-pro para isso.
Independent GitHub snapshot · Automated classification · Original documentation governs
name: "browser-automation" description: "Use quando o usuário pedir para automatizar tarefas no navegador, fazer scraping de sites, preencher formulários, capturar screenshots, extrair dados estruturados de páginas web ou construir workflows de automação web. NÃO para testes — use playwright-pro para isso." agents:
A skill de Browser Automation fornece ferramentas abrangentes e conhecimento para construir workflows de automação web de nível produção usando Playwright. Esta skill cobre extração de dados, preenchimento de formulários, captura de screenshots, gerenciamento de sessão e padrões anti-detecção para automação de navegador confiável em escala.
Quando usar esta skill:
Quando NÃO usar esta skill:
Por que Playwright em vez de Selenium ou Puppeteer:
sleep() explícito ou waitForElement() necessário para a maioria das açõesplaywright codegen registra suas ações e gera scriptsPrioridade de seletor (do mais ao menos confiável):
data-testid, data-id, ou atributos de dados personalizados — estáveis entre redesigns#id — únicos, mas podem mudar entre deploysarticle, nav, main, section — resilientes a mudanças de CSS.product-card, .price — frágeis se as classes são geradas (ex.: CSS modules)nth-child(), nth-of-type() — último recurso, quebra com mudanças de layoutUse XPath apenas quando o CSS não puder expressar o relacionamento (ex.: travessia de ancestral, seleção baseada em texto).
Estratégias de paginação: botão próximo, baseada em URL (?page=N), scroll infinito, botão carregar mais. Veja data_extraction_recipes.md para handlers completos de paginação e padrões de scroll.
Divida formulários com múltiplos passos em funções discretas por passo. Cada função preenche campos, clica em "Próximo"/"Continuar" e aguarda o próximo passo carregar (mudança de URL ou elemento DOM).
Padrões principais: fluxos de login, formulários de múltiplas páginas, upload de arquivos (incluindo zonas de drag-and-drop), manipulação de dropdowns nativos e personalizados. Veja playwright_browser_api.md para referência completa da API sobre fill(), select_option(), set_input_files() e expect_file_chooser().
await page.screenshot(path="full.png", full_page=True)await page.locator("div.chart").screenshot(path="chart.png")await page.pdf(path="out.pdf", format="A4", print_background=True){page}_{viewport}_{state}.pngVeja playwright_browser_api.md para opções completas de screenshot/PDF.
Padrões principais de extração:
<thead> e linhas <tbody> em dicionários::attr() para atributos)Veja data_extraction_recipes.md para funções completas de extração, análise de preços, utilitários de limpeza de dados e helpers de formato de saída (JSON, CSV, JSONL).
context.cookies() e context.add_cookies()context.storage_state(path="state.json") para salvar, browser.new_context(storage_state="state.json") para restaurarMelhor prática: Salve o estado após o login, reutilize entre sessões de scraping. Verifique a validade da sessão antes de iniciar um trabalho longo — faça uma requisição leve para uma página protegida e verifique se você não é redirecionado para o login. Veja playwright_browser_api.md para detalhes da API de cookie e estado de armazenamento.
Sites modernos detectam automação por múltiplos vetores. Aplique estes em ordem de prioridade:
navigator.webdriver = true via script de inicialização (crítico)random.uniform() entre açõesVeja anti_detection_patterns.md para a pilha de stealth completa: hardening de propriedades do navigator, evasão de fingerprint WebGL/canvas, simulação comportamental (movimento do mouse, velocidade de digitação, padrões de scroll), estratégias de rotação de proxy e URLs de auto-teste de detecção.
wait_for_selector), não o evento de carregamento da páginapage.expect_response("**/api/data*") para interceptar e aguardar chamadas de API específicas>>: page.locator("custom-element >> .inner-class")scroll_into_view_if_needed() para acionar o carregamentoVeja playwright_browser_api.md para estratégias de espera, interceptação de rede e detalhes de Shadow DOM.
TimeoutError, tente seletores alternativos antes de falharpage.screenshot(path="error-state.png") em falhas inesperadas para depuraçãoRetry-AfterVeja anti_detection_patterns.md para a implementação completa de backoff exponencial e classe de limitador de taxa.
Cenário: Extraia dados de produto de uma página única com conteúdo renderizado por JavaScript.
Passos:
headless=False), mude para headless em produçãoquery_selector_all com mapeamento de campoasync def extract_single_page(url, selectors):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
viewport={"width": 1920, "height": 1080},
user_agent="Mozilla/5.0 ..."
)
page = await context.new_page()
await page.goto(url, wait_until="networkidle")
data = await extract_listings(page, selectors["container"], selectors["fields"])
await browser.close()
return data
Cenário: Faça scraping de resultados de busca em 50+ páginas.
Passos:
async def scrape_paginated(base_url, selectors, max_pages=100):
all_data = []
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await (await browser.new_context()).new_page()
await page.goto(base_url)
for page_num in range(max_pages):
items = await extract_listings(page, selectors["container"], selectors["fields"])
all_data.extend(items)
next_btn = page.locator(selectors["next_button"])
if await next_btn.count() == 0 or await next_btn.is_disabled():
break
await next_btn.click()
await page.wait_for_selector(selectors["container"])
await human_delay(800, 2000)
await browser.close()
return all_data
Cenário: Faça login em um portal, navegue por um formulário com múltiplos passos, baixe um relatório.
Passos:
async def authenticated_workflow(credentials, form_data, download_dir):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
state_file = "session_state.json"
# Restaurar ou criar sessão
if os.path.exists(state_file):
context = await browser.new_context(storage_state=state_file)
else:
context = await browser.new_context()
page = await context.new_page()
await login(page, credentials["url"], credentials["user"], credentials["pass"])
await context.storage_state(path=state_file)
page = await context.new_page()
await page.goto(form_data["target_url"])
# Preencher passos do formulário
for step_fn in [fill_step_1, fill_step_2]:
await step_fn(page, form_data)
# Manipular download
async with page.expect_download() as dl_info:
await page.click("button:has-text('Download Report')")
download = await dl_info.value
await download.save_as(os.path.join(download_dir, download.suggested_filename))
await browser.close()
| Script | Propósito | Flags Principais | Saída |
|---|---|---|---|
scraping_toolkit.py | Gera esqueleto de script Playwright para scraping | --url, --selectors, --paginate, --output | Script Python ou config JSON |
form_automation_builder.py | Gera script de automação de preenchimento de formulário a partir de especificação de campo | --fields, --url, --output | Script de automação Python |
anti_detection_checker.py | Audita um script Playwright para vetores de detecção | --file, --verbose | Relatório de risco com pontuação |
Todos os scripts são somente stdlib. Execute python3 <script> --help para uso completo.
Ruim: await page.wait_for_timeout(5000) antes de cada ação.
Bom: Use wait_for_selector, wait_for_url, expect_response ou wait_for_load_state. Esperas hardcoded são instáveis e lentas.
Ruim: Script linear que falha na primeira erro. Bom: Envolva cada interação de página em try/except. Tire screenshots em estado de erro. Implemente retry com backoff exponencial.
Ruim: Fazer scraping sem verificar as diretivas do robots.txt.
Bom: Busque e analise o robots.txt antes de fazer scraping. Respeite o Crawl-delay. Pule caminhos não permitidos. Adicione o nome do seu bot ao User-Agent se executando em escala.
Ruim: Hardcodear nomes de usuário e senhas em arquivos Python.
Bom: Use variáveis de ambiente, arquivos .env (no .gitignore), ou um gerenciador de secrets. Passe credenciais via argumentos CLI.
Ruim: Bombardear um site com 100 requisições/segundo. Bom: Adicione delays aleatórios entre requisições (1-3s para scraping educado). Monitore respostas 429. Implemente backoff exponencial.
Ruim: Depender de nomes de classes gerados automaticamente (.css-1a2b3c) ou aninhamento profundo (div > div > div > span:nth-child(3)).
Bom: Use atributos de dados, HTML semântico ou localizadores baseados em texto. Teste seletores no DevTools do navegador primeiro.
Ruim: Lançar navegadores sem fechá-los, levando a vazamentos de recursos.
Bom: Sempre use try/finally ou gerenciadores de contexto async para garantir que browser.close() seja chamado.
Ruim: Usar headless=False em produção/CI.
Bom: Desenvolva com modo com interface para depuração, implante com headless=True. Use variável de ambiente para alternar: headless = os.environ.get("HEADLESS", "true") == "true".