Scraping BrowserGuiasOtimizando o custo

Soluções de otimização de tráfego de proxy de scraping de navegador

Introdução

Ao usar o Puppeteer para scraping de dados, o consumo de tráfego é uma consideração importante. Especialmente quando se usa serviços de proxy, os custos de tráfego podem aumentar significativamente. Para otimizar o uso de tráfego, podemos adotar as seguintes estratégias:

  1. Interceptação de recursos: Reduzir o consumo de tráfego interceptando solicitações de recursos desnecessárias.
  2. Interceptação de URL de solicitação: Reduzir ainda mais o tráfego interceptando solicitações específicas com base nas características da URL.
  3. Simular dispositivos móveis: Usar configurações de dispositivos móveis para obter versões de página mais leves.
  4. Otimização abrangente: Combinar os métodos acima para alcançar os melhores resultados.

Esquema de otimização 1: Interceptação de recursos

Introdução à interceptação de recursos

No Puppeteer, page.setRequestInterception(true) pode capturar todas as solicitações de rede iniciadas pelo navegador e decidir continuar (request.continue()), encerrar (request.abort()) ou personalizar a resposta (request.respond()).

Este método pode reduzir significativamente o consumo de largura de banda, sendo especialmente adequado para cenários de raspagem, captura de tela e otimização de desempenho.

Tipos de recursos interceptáveis e sugestões

Tipo de RecursoDescriçãoExemploImpacto após a interceptaçãoRecomendação
imageRecursos de imagemImagens JPG/PNG/GIF/WebPAs imagens não serão exibidas⭐ Seguro
fontArquivos de fonteFontes TTF/WOFF/WOFF2Serão usadas as fontes padrão do sistema⭐ Seguro
mediaArquivos de mídiaArquivos de vídeo/áudioO conteúdo de mídia não poderá ser reproduzido⭐ Seguro
manifestWeb App ManifestArquivo de configuração PWAA funcionalidade PWA pode ser afetada⭐ Seguro
prefetchPré-busca de recursos<link rel="prefetch">Impacto mínimo na página⭐ Seguro
stylesheetFolha de estilo CSSArquivos CSS externosOs estilos da página serão perdidos, podendo afetar o layout⚠️ Cuidado
websocketWebSocketConexão de comunicação em tempo realFuncionalidade em tempo real desabilitada⚠️ Cuidado
eventsourceEventos enviados pelo servidorDados push do servidorFuncionalidade push desabilitada⚠️ Cuidado
preflightSolicitação de pré-voo CORSSolicitação OPTIONSAs solicitações de origem cruzada falham⚠️ Cuidado
scriptScripts JavaScriptArquivos JS externosFuncionalidade dinâmica desabilitada, SPA pode não renderizar❌ Evitar
xhrSolicitações XHRSolicitações de dados AJAXImpossível obter dados dinâmicos❌ Evitar
fetchSolicitações FetchSolicitações AJAX modernasImpossível obter dados dinâmicos❌ Evitar
documentDocumento principalPrópria página HTMLA página não pode carregar❌ Evitar

Explicação do nível de recomendação:

  • Seguro: A interceptação quase não tem impacto na raspagem de dados ou na renderização da primeira tela; recomenda-se bloquear por padrão.
  • ⚠️ Cuidado: Pode quebrar estilos, funções em tempo real ou solicitações de origem cruzada; requer julgamento comercial.
  • Evitar: Alta probabilidade de causar falha na renderização ou obtenção de dados normalmente em sites SPA/dinâmicos, a menos que você tenha certeza absoluta de que não precisa desses recursos.

Exemplo de código de interceptação de recursos

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 interceptação de solicitação
    await page.setRequestInterception(true);
 
    // Definir os tipos de recursos a bloquear
    const BLOCKED_TYPES = new Set([
        'image',
        'font',
        'media',
        'stylesheet',
    ]);
 
    // Interceptar solicitaçõ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')
    .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 solicitaçã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 solicitações de terceiros desnecessárias.

Estratégias de interceptação de URL

  1. Interceptar por domínio: Bloquear todas as solicitações de um domínio específico
  2. Interceptar por caminho: Bloquear solicitações de um caminho específico
  3. Interceptar por tipo de arquivo: Bloquear arquivos com extensões específicas
  4. Interceptar por palavra-chave: Bloquear solicitações cujas URLs contenham palavras-chave específicas

Padrões de URL interceptáveis comuns

Padrão de URLDescriçãoExemploRecomendação
Serviços de publicidadeDomínios de rede de publicidadead.doubleclick.net, googleadservices.com⭐ Seguro
Serviços de análiseScripts de estatísticas e análisesgoogle-analytics.com, hotjar.com⭐ Seguro
Plugins de mídia socialBotões de compartilhamento social, etc.platform.twitter.com, connect.facebook.net⭐ Seguro
Pixels de rastreamentoPixels que rastreiam o comportamento do usuárioURLs contendo pixel, beacon, tracker⭐ Seguro
Arquivos de mídia grandesVídeos e arquivos de áudio grandesExtensões como .mp4, .webm, .mp3⭐ Seguro
Serviços de fonteServiços de fonte onlinefonts.googleapis.com, use.typekit.net⭐ Seguro
Recursos CDNCDN de recursos estáticoscdn.jsdelivr.net, unpkg.com⚠️ Cuidado

Exemplo de código de interceptação de URL

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 interceptação de solicitação
    await page.setRequestInterception(true);
 
    // Definir domínios e padrões de URL a 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 solicitaçõ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 solicitaçõ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 porque os sites móveis geralmente fornecem conteúdo de página mais leve.

Vantagens da simulação de dispositivos móveis

  1. Versões de página mais leves: Muitos sites fornecem conteúdo mais conciso para dispositivos móveis
  2. Recursos de imagem menores: As versões móveis geralmente carregam imagens menores
  3. CSS e JavaScript simplificados: As versões móveis geralmente usam estilos e scripts simplificados
  4. Anúncios e conteúdo não essenciais reduzidos: As versões móveis geralmente removem algumas funcionalidades não essenciais
  5. 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 usados:

const iPhoneX = {
    viewport: {
        width: 375,
        height: 812,
        deviceScaleFactor: 3,
        isMobile: true,
        hasTouch: true,
        isLandscape: false
    }
};

Ou usar diretamente os métodos integrados do puppeteer para simular dispositivos móveis

import { KnownDevices } from 'puppeteer-core';
const iPhone = KnownDevices['iPhone 15 Pro'];
 
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);

Exemplo de código de simulação de dispositivos móveis

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 scrapeWithMobileEmulation(url) {
    const browser = await puppeteer.connect({
        browserWSEndpoint: scrapelessUrl,
        defaultViewport: null
    });
 
    const page = await browser.newPage();
 
    // Definir simulação de dispositivo móvel
    const iPhone = KnownDevices['iPhone 15 Pro'];
    await page.emulate(iPhone);
 
    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
scrapeWithMobileEmulation('https://www.scrapeless.com')
    .then(data => console.log('Resultado da raspagem:', data))
    .catch(error => console.error('Raspagem falhou:', error));

Exemplo de otimização abrangente

Aqui está um exemplo abrangente combinando todos os esquemas de otimização:

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 optimizedScraping(url) {
    console.log(`Iniciando raspagem otimizada: ${url}`);
 
    // Registrar o uso de tráfego
    let totalBytesUsed = 0;
 
    const browser = await puppeteer.connect({
        browserWSEndpoint: scrapelessUrl,
        defaultViewport: null
    });
 
    const page = await browser.newPage();
 
    // Definir simulação de dispositivo móvel
    const iPhone = KnownDevices['iPhone 15 Pro'];
    await page.emulate(iPhone);
 
    // Definir interceptação de solicitação
    await page.setRequestInterception(true);
 
    // Definir os tipos de recursos a bloquear
    const BLOCKED_TYPES = [
        'image',
        'media',
        'font'
    ];
 
    // Definir domínios a bloquear
    const BLOCKED_DOMAINS = [
        'google-analytics.com',
        'googletagmanager.com',
        'facebook.net',
        'doubleclick.net',
        'adservice.google.com'
    ];
 
    // Definir caminhos de URL a bloquear
    const BLOCKED_PATHS = [
        '/ads/',
        '/analytics/',
        '/tracking/'
    ];
 
    // Interceptar solicitações
    page.on('request', (request) => {
        const url = request.url();
        const resourceType = request.resourceType();
 
        // Verificar tipo de recurso
        if (BLOCKED_TYPES.includes(resourceType)) {
            console.log(`Tipo de recurso bloqueado: ${resourceType} - ${url.substring(0, 50)}...`);
            request.abort();
            return;
        }
 
        // Verificar domínio
        if (BLOCKED_DOMAINS.some(domain => url.includes(domain))) {
            console.log(`Domínio bloqueado: ${url.substring(0, 50)}...`);
            request.abort();
            return;
        }
 
        // Verificar caminho
        if (BLOCKED_PATHS.some(path => url.includes(path))) {
            console.log(`Caminho bloqueado: ${url.substring(0, 50)}...`);
            request.abort();
            return;
        }
 
        // Permitir outras solicitações
        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 disparar conteúdo de carregamento lento
    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
            }))
        };
    });
 
    // Saída de estatísticas de uso de 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('Raspagem concluída:', data))
    .catch(error => console.error('Raspagem falhou:', error));

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:

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 raspagem otimizada: ${url}`);
 
  // Registrar o uso de tráfego
  let totalBytesUsed = 0;
 
  const browser = await puppeteer.connect({
    browserWSEndpoint: scrapelessUrl,
    defaultViewport: null
  });
 
  const page = await browser.newPage();
 
  // Definir interceptação de solicitação
  await page.setRequestInterception(true);
 
  // Interceptar solicitaçõ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 disparar conteúdo de carregamento lento
  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
      }))
    };
  });
 
  // Saída de estatísticas de uso de 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('Raspagem concluída:', data))
  .catch(error => console.error('Raspagem falhou:', error));

Após executar o código não otimizado, podemos ver a diferença de tráfego de forma muito intuitiva a partir das informações impressas:

CenárioTráfego usado (MB)Taxa de economia
Não otimizado6.03
Otimizado0.81≈ 86.6 %

Combinando os esquemas de otimização acima, o consumo de tráfego de proxy pode ser reduzido significativamente, a eficiência de raspagem pode ser melhorada e garantindo que o conteúdo essencial necessário seja obtido.