# Etapa 03 — Motor de scraper com Playwright ## Objetivo Implementar o módulo `scraper/` responsável por abrir o navegador, buscar no Google Maps pelo termo e localização informados, rolar o painel de resultados até esgotar os leads e extrair os dados brutos de cada card. ## Contexto Nesta etapa ainda **não** há rotação de proxy nem delays humanizados sofisticados (isso é a etapa 05) — o objetivo aqui é o motor de extração funcionar de ponta a ponta em um ambiente controlado, sem se preocupar ainda com bloqueio. Também não há padronização dos dados ainda (etapa 04) — os dados saem brutos, exatamente como capturados da página. ## Tarefas 1. Adicionar a dependência do Playwright for Java ao projeto e rodar o comando de instalação dos browsers (`mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install chromium"` ou equivalente) 2. Criar `scraper/GoogleMapsScraperService`, responsável por: - Abrir uma nova instância de navegador Chromium (headless configurável via propriedade, para permitir debug visual em dev) - Navegar até `google.com/maps`, localizar o campo de busca, digitar `termo_busca + localizacao` e submeter - Aguardar o painel de resultados lateral carregar 3. Criar `scraper/ScrollExtractorService`, responsável por: - Rolar o painel de resultados (não a página inteira) em incrementos, aguardando carregamento entre cada scroll - Detectar o fim da lista (quando o número de resultados carregados para de crescer após N tentativas de scroll) 4. Criar `scraper/LeadRawExtractor`, responsável por: - Para cada card de resultado, extrair via seletor: nome, categoria (texto bruto), endereço (texto bruto), telefone (texto bruto), site, `place_id` (se disponível na URL/atributo do elemento), avaliação - Retornar uma lista de DTOs `LeadBrutoDTO` (sem nenhuma padronização ainda) 5. Criar `scraper/BuscaOrchestrator`, que: - Recebe uma `Busca` (entidade), executa os passos acima em sequência, e retorna a lista de `LeadBrutoDTO` extraída - Captura exceções de forma que uma falha em um card não interrompa a extração dos demais 6. Testar manualmente com pelo menos 3 combinações diferentes de termo/localização, incluindo um caso com poucos resultados (< 10) e um com muitos (> 50, para validar o scroll) ## Critérios de aceite - [ ] Motor consegue abrir o Maps, buscar e extrair resultados de uma busca simples de ponta a ponta - [ ] Scroll continua até esgotar os resultados reais (validado manualmente comparando com o número exibido no Maps) - [ ] Extração captura nome, telefone bruto, endereço bruto, categoria bruta, site e `place_id` quando disponíveis - [ ] Falha em um único card não derruba a extração dos demais - [ ] Testado com pelo menos 3 buscas diferentes de ramos/localizações distintas