Otimizando o Tráfego de Navegador Headless: Estratégias de Redução de Custos com Puppeteer para Extração de Dados Eficiente

Senior Web Scraping Engineer
Visão Geral
Ao usar o Puppeteer para rastreamento de dados, o consumo de tráfego é uma consideração importante. Especialmente ao usar serviços de proxy, os custos de tráfego podem aumentar significativamente. Para otimizar o uso do tráfego, podemos adotar as seguintes estratégias:
- Intercepção de recursos: Reduzir o consumo de tráfego interceptando solicitações de recursos desnecessárias.
- Intercepção de URLs de solicitação: Reduzir ainda mais o tráfego interceptando solicitações específicas com base nas características da URL.
- Simular dispositivos móveis: Usar configurações de dispositivos móveis para obter versões de página mais leves.
- Otimização abrangente: Combinar os métodos acima para obter os melhores resultados.
Esquema de Otimização 1: Intercepção de Recursos
Introdução à Intercepção de Recursos
No Puppeteer, page.setRequestInterception(true)
pode capturar cada solicitação de rede iniciada pelo navegador e decidir continuar (request.continue()
), encerrar (request.abort()
) ou personalizar a resposta (request.respond()
).
Esse método pode reduzir significativamente o consumo de largura de banda, especialmente adequado para cenários de rastreamento, captura de tela e otimização de desempenho.
Tipos de Recursos Interceptáveis e Sugestões
Tipo de Recurso | Descrição | Exemplo | Impacto Após Intercepção | Recomendação |
---|---|---|---|---|
imagem |
Recursos de imagem | Imagens JPG/PNG/GIF/WebP | Imagens não serão exibidas | ⭐ Seguro |
fonte |
Arquivos de fonte | Fontes TTF/WOFF/WOFF2 | Fontes padrão do sistema serão usadas | ⭐ Seguro |
mídia |
Arquivos de mídia | Arquivos de vídeo/áudio | Conteúdo de mídia não pode ser reproduzido | ⭐ Seguro |
manifesto |
Manifesto da Web App | Arquivo de configuração PWA | Funcionalidade PWA pode ser afetada | ⭐ Seguro |
prefetch |
Recursos de pré-carregamento | <link rel="prefetch"> |
Impacto mínimo na página | ⭐ Seguro |
folha de estilo |
Folha de estilo CSS | Arquivos CSS externos | Estilos da página são perdidos, pode afetar o layout | ⚠️ Cuidado |
websocket |
WebSocket | Conexão de comunicação em tempo real | Funcionalidade em tempo real desativada | ⚠️ Cuidado |
eventsource |
Eventos Enviados pelo Servidor | Dados de push do servidor | Funcionalidade de push desativada | ⚠️ Cuidado |
preflight |
Solicitação de preflight CORS | Solicitação OPTIONS | Solicitações de origem cruzada falharão | ⚠️ Cuidado |
script |
Scripts JavaScript | Arquivos JS externos | Funcionalidade dinâmica desativada, SPA pode não renderizar | ❌ Evitar |
xhr |
Solicitações XHR | Solicitações de dados AJAX | Incapaz de obter dados dinâmicos | ❌ Evitar |
fetch |
Solicitações Fetch | Solicitações AJAX modernas | Incapaz de obter dados dinâmicos | ❌ Evitar |
documento |
Documento principal | Página HTML em si | Página não pode carregar | ❌ Evitar |
Explicação do Nível de Recomendação:
- ⭐ Seguro: A intercepção tem quase nenhum impacto na raspagem de dados ou na renderização da primeira tela; é recomendável bloquear por padrão.
- ⚠️ Cuidado: Pode quebrar estilos, funções em tempo real ou solicitações de origem cruzada; requer julgamento de negócios.
- ❌ Evitar: Alta probabilidade de causar falha na renderização ou na obtenção de dados normais em sites dinâmicos/SPA, a menos que você tenha absoluta certeza de que não precisa desses recursos.
Exemplo de Código de Intercepção de Recursos
javascript
import puppeteer from 'puppeteer-core';
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';
async function scrapeWithResourceBlocking(url) {
const browser = await puppeteer.connect({
browserWSEndpoint: scrapelessUrl,
defaultViewport: null
});
const page = await browser.newPage();
// Habilitar intercepção de requisições
await page.setRequestInterception(true);
// Definir tipos de recurso a serem bloqueados
const BLOCKED_TYPES = new Set([
'imagem',
'fonte',
'mídia',
'folha de estilo',
]);
// Interceptar requisições
page.on('request', (request) => {
if (BLOCKED_TYPES.has(request.resourceType())) {
request.abort();
console.log(`Bloqueado: ${request.resourceType()} - ${request.url().substring(0, 50)}...`);
} else {
request.continue();
}
});
await page.goto(url, {waitUntil: 'domcontentloaded'});
// Extrair dados
const data = await page.evaluate(() => {
return {
title: document.title,
content: document.body.innerText.substring(0, 1000)
};
});
await browser.close();
return data;
}
// Uso
scrapeWithResourceBlocking('https://www.scrapeless.com');
javascript
.then(data => console.log('Resultado da raspagem:', data))
.catch(error => console.error('Raspagem falhou:', error));
Esquema de Otimização 2: Interceptação de URL de Requisição
Além de interceptar por tipo de recurso, um controle de interceptação mais granular pode ser realizado com base nas características da URL. Isso é particularmente eficaz para bloquear anúncios, scripts de análise e outras requisições de terceiros desnecessárias.
Estratégias de Interceptação de URL
- Interceptar por domínio: Bloquear todas as requisições de um domínio específico
- Interceptar por caminho: Bloquear requisições de um caminho específico
- Interceptar por tipo de arquivo: Bloquear arquivos com extensões específicas
- Interceptar por palavra-chave: Bloquear requisições cujas URLs contenham palavras-chave específicas
Padrões Comuns de URL Interceptáveis
Padrão de URL | Descrição | Exemplo | Recomendação |
---|---|---|---|
Serviços de publicidade | Domínios de redes publicitárias | ad.doubleclick.net , googleadservices.com |
⭐ Seguro |
Serviços de análise | Scripts de estatísticas e análise | google-analytics.com , hotjar.com |
⭐ Seguro |
Plugins de redes sociais | Botões de compartilhamento social | platform.twitter.com , connect.facebook.net |
⭐ Seguro |
Pixels de rastreamento | Pixels que rastreiam o comportamento do usuário | URLs contendo pixel , beacon , tracker |
⭐ Seguro |
Arquivos de mídia grandes | Arquivos de vídeo e áudio grandes | Extensões como .mp4 , .webm , .mp3 |
⭐ Seguro |
Serviços de fontes | Serviços de fonte online | fonts.googleapis.com , use.typekit.net |
⭐ Seguro |
Recursos de CDN | CDN de recursos estáticos | cdn.jsdelivr.net , unpkg.com |
⚠️ Cuidado |
Exemplo de Código de Interceptação de URL
javascript
import puppeteer from 'puppeteer-core';
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';
async function scrapeWithUrlBlocking(url) {
const browser = await puppeteer.connect({
browserWSEndpoint: scrapelessUrl,
defaultViewport: null
});
const page = await browser.newPage();
// Habilitar a interceptação de requisições
await page.setRequestInterception(true);
// Definir domínios e padrões de URL para bloquear
const BLOCKED_DOMAINS = [
'google-analytics.com',
'googletagmanager.com',
'doubleclick.net',
'facebook.net',
'twitter.com',
'linkedin.com',
'adservice.google.com',
];
const BLOCKED_PATHS = [
'/ads/',
'/analytics/',
'/pixel/',
'/tracking/',
'/stats/',
];
// Interceptar requisições
page.on('request', (request) => {
const url = request.url();
// Verificar domínio
if (BLOCKED_DOMAINS.some(domain => url.includes(domain))) {
request.abort();
console.log(`Domínio bloqueado: ${url.substring(0, 50)}...`);
return;
}
// Verificar caminho
if (BLOCKED_PATHS.some(path => url.includes(path))) {
request.abort();
console.log(`Caminho bloqueado: ${url.substring(0, 50)}...`);
return;
}
// Permitir outras requisições
request.continue();
});
await page.goto(url, { waitUntil: 'domcontentloaded' });
// Extrair dados
const data = await page.evaluate(() => {
return {
title: document.title,
content: document.body.innerText.substring(0, 1000)
};
});
await browser.close();
return data;
}
// Uso
scrapeWithUrlBlocking('https://www.scrapeless.com')
.then(data => console.log('Resultado da raspagem:', data))
.catch(error => console.error('Raspagem falhou:', error));
Esquema de Otimização 3: Simular Dispositivos Móveis
Simular dispositivos móveis é outra estratégia eficaz de otimização de tráfego, pois sites móveis geralmente apresentam conteúdo de página mais leve.
Vantagens da Simulação de Dispositivos Móveis
- Versões de página mais leves: Muitos sites fornecem conteúdo mais conciso para dispositivos móveis
- Recursos de imagem menores: As versões móveis geralmente carregam imagens menores
- CSS e JavaScript simplificados: As versões móveis geralmente usam estilos e scripts simplificados
- Redução de anúncios e conteúdo não essencial: As versões móveis costumam remover algumas funcionalidades não essenciais
- Resposta adaptativa: Obter layouts de conteúdo otimizados para telas pequenas
Configuração de Simulação de Dispositivos Móveis
Aqui estão os parâmetros de configuração para vários dispositivos móveis comumente utilizados:
javascript
const iPhoneX = {
viewport: {
width: 375,
height: 812,
deviceScaleFactor: 3,
isMobile: true,
hasTouch: true,
isLandscape: false
}
};
Ou use diretamente os métodos embutidos do puppeteer para simular dispositivos móveis
javascript
import { KnownDevices } from 'puppeteer-core';
const iPhone = KnownDevices['iPhone 15 Pro'];
javascript
const navegador = await puppeteer.launch();
const pagina = await navegador.newPage();
await pagina.emulate(iPhone);
Exemplo de Código de Simulação de Dispositivo Móvel
javascript
import puppeteer, {KnownDevices} from 'puppeteer-core';
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';
async function rasparComEmulaçãoMóvel(url) {
const navegador = await puppeteer.connect({
browserWSEndpoint: scrapelessUrl,
defaultViewport: null
});
const pagina = await navegador.newPage();
// Definir simulação de dispositivo móvel
const iPhone = KnownDevices['iPhone 15 Pro'];
await pagina.emulate(iPhone);
await pagina.goto(url, {waitUntil: 'domcontentloaded'});
// Extrair dados
const dados = await pagina.evaluate(() => {
return {
título: document.title,
conteúdo: document.body.innerText.substring(0, 1000)
};
});
await navegador.close();
return dados;
}
// Uso
rasparComEmulaçãoMóvel('https://www.scrapeless.com')
.then(dados => console.log('Resultado da raspagem:', dados))
.catch(erro => console.error('Raspagem falhou:', erro));
Exemplo Abrangente de Otimização
Aqui está um exemplo abrangente combinando todos os esquemas de otimização:
javascript
import puppeteer, {KnownDevices} from 'puppeteer-core';
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';
async function raspagemOtimizada(url) {
console.log(`Iniciando raspagem otimizada: ${url}`);
// Registrar uso de tráfego
let totalBytesUsados = 0;
const navegador = await puppeteer.connect({
browserWSEndpoint: scrapelessUrl,
defaultViewport: null
});
const pagina = await navegador.newPage();
// Definir simulação de dispositivo móvel
const iPhone = KnownDevices['iPhone 15 Pro'];
await pagina.emulate(iPhone);
// Definir interceptação de requisições
await pagina.setRequestInterception(true);
// Definir tipos de recursos para bloquear
const TIPOS_BLOQUEADOS = [
'imagem',
'mídia',
'fonte'
];
// Definir domínios para bloquear
const DOMÍNIOS_BLOQUEADOS = [
'google-analytics.com',
'googletagmanager.com',
'facebook.net',
'doubleclick.net',
'adservice.google.com'
];
// Definir caminhos de URL para bloquear
const CAMINHOS_BLOQUEADOS = [
'/ads/',
'/analytics/',
'/tracking/'
];
// Interceptar requisições
pagina.on('request', (request) => {
const url = request.url();
const tipoRecurso = request.resourceType();
// Verificar tipo de recurso
if (TIPOS_BLOQUEADOS.includes(tipoRecurso)) {
console.log(`Tipo de recurso bloqueado: ${tipoRecurso} - ${url.substring(0, 50)}...`);
request.abort();
return;
}
// Verificar domínio
if (DOMÍNIOS_BLOQUEADOS.some(dominio => url.includes(dominio))) {
console.log(`Domínio bloqueado: ${url.substring(0, 50)}...`);
request.abort();
return;
}
// Verificar caminho
if (CAMINHOS_BLOQUEADOS.some(caminho => url.includes(caminho))) {
console.log(`Caminho bloqueado: ${url.substring(0, 50)}...`);
request.abort();
return;
}
// Permitir outras requisições
request.continue();
});
// Monitorar tráfego de rede
pagina.on('response', async (response) => {
const headers = response.headers();
const contentLength = headers['content-length'] ? parseInt(headers['content-length'], 10) : 0;
totalBytesUsados += contentLength;
});
await pagina.goto(url, {waitUntil: 'domcontentloaded'});
// Simular rolagem para ativar conteúdo carregado sob demanda
await pagina.evaluate(() => {
window.scrollBy(0, window.innerHeight);
});
await new Promise(resolve => setTimeout(resolve, 1000))
// Extrair dados
const dados = await pagina.evaluate(() => {
return {
título: document.title,
conteúdo: document.body.innerText.substring(0, 1000),
links: Array.from(document.querySelectorAll('a')).slice(0, 10).map(a => ({
texto: a.innerText,
href: a.href
}))
};
});
// Saída das estatísticas de uso de tráfego
console.log(`\nEstatísticas de Uso de Tráfego:`);
console.log(`Usado: ${(totalBytesUsados / 1024 / 1024).toFixed(2)} MB`);
await navegador.close();
return dados;
}
// Uso
raspagemOtimizada('https://www.scrapeless.com')
.then(dados => console.log('Raspagem completa:', dados))
.catch(erro => console.error('Raspagem falhou:', erro));
Comparação de Otimização
Tentamos remover o código otimizado do exemplo abrangente para comparar o tráfego antes e depois da otimização. Aqui está o código de exemplo não otimizado:
javascript
import puppeteer from 'puppeteer-core';
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';
async function optimizedScraping(url) {
console.log(Iniciando extração otimizada: ${url}
);
// Registrar uso de tráfego
let totalBytesUsed = 0;
const browser = await puppeteer.connect({
browserWSEndpoint: scrapelessUrl,
defaultViewport: null
});
const page = await browser.newPage();
// Configurar interceptação de requisições
await page.setRequestInterception(true);
// Interceptar requisições
page.on('request', (request) => {
request.continue();
});
// Monitorar tráfego de rede
page.on('response', async (response) => {
const headers = response.headers();
const contentLength = headers['content-length'] ? parseInt(headers['content-length'], 10) : 0;
totalBytesUsed += contentLength;
});
await page.goto(url, {waitUntil: 'domcontentloaded'});
// Simular rolagem para acionar o carregamento preguiçoso de conteúdo
await page.evaluate(() => {
window.scrollBy(0, window.innerHeight);
});
await new Promise(resolve => setTimeout(resolve, 1000))
// Extrair dados
const data = await page.evaluate(() => {
return {
title: document.title,
content: document.body.innerText.substring(0, 1000),
links: Array.from(document.querySelectorAll('a')).slice(0, 10).map(a => ({
text: a.innerText,
href: a.href
}))
};
});
// Exibir estatísticas de uso do tráfego
console.log(\nEstatísticas de Uso de Tráfego:
);
console.log(Usado: ${(totalBytesUsed / 1024 / 1024).toFixed(2)} MB
);
await browser.close();
return data;
}
// Uso
optimizedScraping('https://www.scrapeless.com')
.then(data => console.log('Extração completa:', data))
.catch(error => console.error('Extração falhou:', error));
Após executar o código não otimizado, podemos ver a diferença de tráfego muito intuitivamente a partir das informações impressas:
Cenário | Tráfego Usado (MB) | Taxa de Economia |
---|---|---|
Não Otimizado | 6.03 | — |
Otimizado | 0.81 | ≈ 86,6 % |
Ao combinar os esquemas de otimização acima, o consumo de tráfego do proxy pode ser significativamente reduzido, a eficiência da extração pode ser melhorada e garantindo que o conteúdo central necessário seja obtido.
Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.