APRENDIZADO & COGNIÇÃO
Web Scraping eficiente: Do Headless Browser às APIs ocultas
Quando você decide criar um agregador de dados em tempo real, a primeira ideia que vem à cabeça para coletar…

Quando você decide criar um agregador de dados em tempo real, a primeira ideia que vem à cabeça para coletar informações de grandes plataformas é: “Vou subir um Puppeteer, simular cliques humanos e pronto”.
Foi exatamente isso que fiz quando comecei a construir a base de dados do NaveIdeal, uma plataforma criada para minerar, higienizar e auditar ofertas de veículos de múltiplos portais (como OLX, WebMotors e iCarros) em tempo real, calculando a defasagem contra a Tabela FIPE para ranquear as melhores oportunidades do mercado.
No papel, parecia perfeito. Na prática, me fez desistir do projeto no primeiro mês.
Neste post, quero compartilhar as 3 fases de maturidade de Web Scraping pelas quais passei, os erros de consumo de memória que quase derrubaram a infraestrutura e como saí de instâncias pesadas de Chromium para requisições de alta performance consumindo frações míseras de CPU e RAM.
1. O Ponto de Partida e o Pesadelo da RAM (Puppeteer)
No início, para garantir que as páginas carregassem scripts dinâmicos e contornassem desafios visuais, configurei uma fila usando puppeteer-cluster e puppeteer-extra-plugin-stealth.
A lógica de extração era parecida com isto:
async function scrapeComBrowser(page, url) { await page.goto(url, { waitUntil: "domcontentloaded", timeout: 60000 }); await page.waitForSelector("#price-box-container", { timeout: 10000 }); const dados = await page.evaluate(() => { const titulo = document.querySelector("h1")?.innerText || ""; const preco = document.querySelector("#price-box-container")?.innerText || ""; return { titulo, preco }; }); return dados;}
Onde a conta não fechava:
Consumo de Memória: Cada aba ou instância do Chromium consome facilmente entre 150 MB e 350 MB de RAM. Multiplique isso por uma concorrência mínima de 4 workers em um servidor modesto e você terá a máquina travando ou muito lenta.
Overhead de CPU: O Chromium renderiza CSS (mas temos como configurar para o puppeteer não renderizar isso), calcula layout e processa scripts que você não precisa para nada se o seu objetivo for apenas extrair texto e JSON.
Fragilidade e Timeouts: Quedas de conexão no protocolo do DevTools (protocolTimeout) eram comuns durante varreduras contínuas.
2. A Virada de Chave: HTTP Puro + Cheerio
Percebi que em 80% das páginas que eu precisava varrer, o HTML inicial já vinha com o conteúdo renderizado no servidor (SSR) ou embutido em tags iniciais. Eu não precisava executar JavaScript no cliente, precisava apenas fazer o download do HTML cru e fazer o parse da árvore estática.
Trocamos o Puppeteer por um cliente HTTP otimizado (com suporte a proxies residenciais e headers humanizados) aliado ao Cheerio (uma implementação rápida e leve do núcleo do jQuery voltada para o servidor).
const cheerio = require("cheerio");const proxyManager = require("./services/proxyManager");//aqui esta configurado os proxys residenciasasync function scrapeComCheerio(url) { const response = await proxyManager.fetch({ url }); const $ = cheerio.load(response.body); const title = $("h1").first().text().trim(); const precoTxt = $("#price-box-container").text().trim(); const preco = Number(precoTxt.replace(/D/g, "")); return { title, preco };}
O impacto imediato:
Memória RAM: Caiu de centenas de megabytes por worker para menos de 30 MB no processo total.
Velocidade: Uma requisição que as vezes levava até 10 ou 15 segundos no Chromium passou a ser resolvida em 500ms a 1.2s.
3. O Santo Graal: Mineração Direta de APIs e Payloads Ocultos
Se usar Cheerio já reduziu o consumo em 80%, a descoberta seguinte mudou completamente o jogo: muitos portais modernos trafegam dados estruturados por trás das cortinas.
Em vez de fazer o scraping visual de dezenas de elementos (.div > span > a), começamos a inspecionar a aba Network das plataformas. Descobrimos que portais robustos como a WebMotors alimentam suas listagens e telas através de APIs REST internas ou dados serializados.
No extrator do NaveIdeal, em vez de baixar todo o HTML de uma listagem para caçar tags CSS, consumimos diretamente os endpoints de busca com filtros ordenados:
async function extrairViaApiInterna(estado, tipo, pagina = 1) { const apiUrl = `https://www.site.com.br/api/search/${tipo}?state=${estado}&actualPage=${pagina}&displayPerPage=24`; const response = await proxyManager.fetch({ url: apiUrl, headers: { "Accept": "application/json", "Origin": "https://www.site.com.br" } }); const json = JSON.parse(response.body); const anuncios = json.SearchResults || []; return anuncios.map(item => ({ id: item.UniqueId, marca: item.Specification?.Make?.Value, modelo: item.Specification?.Model?.Value, versao: item.Specification?.Version?.Value, ano: item.Specification?.YearModel, preco: item.Prices?.Price, fotos: item.Media?.Photos?.map(p => p.PhotoPath) }));}
Por que isso é superior?
Zero quebra de layout: Se a plataforma mudar a cor do botão ou a classe CSS do preço de .ad-price para .sc-price-new, o seu scraper tradicional quebra. A API estruturada tende a ser muito mais estável.
Custo Computacional Quase Zero: Fazer o parse de uma string JSON nativa com JSON.parse() é ordens de grandeza mais rápido do que construir e percorrer nós de DOM.
Onde tudo isso se conecta?
Todo esse processo de extração leve alimenta o pipeline do NaveIdeal.
Depois que esses dados brutos chegam sem peso na infraestrutura, eles entram em uma camada de normalização semântica, cruzam com a base histórica da Tabela FIPE e geram um Score de Oportunidade para filtrar veículos com real margem de desconto versus distorções de mercado.
Perguntas frequentes
Respostas institucionais sobre esta cobertura, fontes e limites editoriais.
- Sobre o que trata “Web Scraping eficiente: Do Headless Browser às APIs ocultas”?
- Quando você decide criar um agregador de dados em tempo real, a primeira ideia que vem à cabeça para coletar informações de grandes plataformas é: "Vou subir um Puppeteer, simular cliques humanos e pronto".Foi exatamente isso…
- Por que Aprendizado & Cognição importa agora?
- O tema impacta decisões e debates cotidianos ligados a Aprendizado & Cognição. A redação destaca fatos, datas e implicações práticas sem substituir orientação profissional personalizada.
- Quem edita o conteúdo do Estrato Mente?
- A cobertura é produzida e revisada pela equipe editorial do Estrato Mente, com editor-chefe responsável pela linha editorial. Conheça a redação em https://mente.estrato.cc/equipe/.
- Quais fontes o Estrato prioriza?
- Priorizamos fontes primárias (órgãos oficiais, balanços, estudos revisados, documentos públicos) e cruzamos informações antes da publicação, conforme a política editorial.
- Como solicitar correção de uma matéria?
- Envie o pedido pela página de Correções (https://mente.estrato.cc/correcoes/) ou Contato (https://mente.estrato.cc/contato/). Erros materiais são corrigidos com registro da atualização.
- O conteúdo constitui aconselhamento profissional?
- Não. As matérias têm caráter informativo e jornalístico. Decisões financeiras, de saúde, jurídicas ou educacionais devem considerar profissionais habilitados e a sua situação particular.
- Onde acompanhar a política editorial do Estrato Mente?
- Metodologia, ética e transparência estão em https://mente.estrato.cc/metodologia/, https://mente.estrato.cc/etica-editorial/ e https://mente.estrato.cc/politica-editorial/.
- Como o Estrato trata temas sensíveis (YMYL)?
- Temas que afetam dinheiro, saúde e bem-estar recebem revisão editorial reforçada, disclaimer visível e links para páginas institucionais de metodologia e correções. Portal: https://mente.estrato.cc/
[…] Web Scraping eficiente: Do Headless Browser às APIs ocultas […]