Volver al blog

¿Cómo optimizar el uso de tráfico de tu navegador al máximo?

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

26-Apr-2025

Resumen

Al utilizar Puppeteer para la recopilación de datos, el consumo de tráfico es una consideración importante. Especialmente al utilizar servicios de proxy, los costos de tráfico pueden aumentar significativamente. Para optimizar el uso del tráfico, podemos adoptar las siguientes estrategias:

  1. Intercepción de recursos: Reducir el consumo de tráfico interceptando solicitudes de recursos innecesarias.
  2. Intercepción de URL de solicitud: Reducir aún más el tráfico interceptando solicitudes específicas basadas en las características de la URL.
  3. Simular dispositivos móviles: Usar configuraciones de dispositivos móviles para obtener versiones más ligeras de las páginas.
  4. Optimización integral: Combinar los métodos anteriores para lograr los mejores resultados.

Esquema de Optimización 1: Intercepción de Recursos

Introducción a la Intercepción de Recursos

En Puppeteer, page.setRequestInterception(true) puede capturar cada solicitud de red iniciada por el navegador y decidir continuar (request.continue()), terminar (request.abort()) o personalizar la respuesta (request.respond()).

Este método puede reducir significativamente el consumo de ancho de banda, especialmente adecuado para escenarios de raspado, captura de pantallas y optimización de rendimiento.

Tipos de Recursos Interceptables y Sugerencias

Tipo de Recurso Descripción Ejemplo Impacto Después de la Intercepción Recomendación
image Recursos de imagen Imágenes JPG/PNG/GIF/WebP Las imágenes no se mostrarán ⭐ Seguro
font Archivos de fuente Fuentes TTF/WOFF/WOFF2 Se usarán fuentes predeterminadas del sistema en su lugar ⭐ Seguro
media Archivos de medios Archivos de video/audio No se podrá reproducir contenido multimedia ⭐ Seguro
manifest Manifiesto de aplicación web Archivo de configuración de PWA La funcionalidad de PWA puede verse afectada ⭐ Seguro
prefetch Recursos de prefetch <link rel="prefetch"> Impacto mínimo en la página ⭐ Seguro
stylesheet Hoja de estilo CSS Archivos CSS externos Se perderán los estilos de la página, puede afectar el diseño ⚠️ Precaución
websocket WebSocket Conexión de comunicación en tiempo real Funcionalidad en tiempo real deshabilitada ⚠️ Precaución
eventsource Eventos enviados por el servidor Datos de push del servidor Funcionalidad push deshabilitada ⚠️ Precaución
preflight Solicitud de preflight CORS Solicitud OPTIONS Las solicitudes de origen cruzado fallan ⚠️ Precaución
script Scripts de JavaScript Archivos JS externos Funcionalidad dinámica desactivada, SPA puede no renderizar ❌ Evitar
xhr Solicitudes XHR Solicitudes de datos AJAX No se pueden obtener datos dinámicos ❌ Evitar
fetch Solicitudes Fetch Solicitudes AJAX modernas No se pueden obtener datos dinámicos ❌ Evitar
document Documento principal La página HTML misma La página no puede cargarse ❌ Evitar

Explicación del Nivel de Recomendación:

  • Seguro: La intercepción tiene casi ningún impacto en la recopilación de datos o en el renderizado de la primera pantalla; se recomienda bloquear de forma predeterminada.
  • ⚠️ Precaución: Puede romper estilos, funciones en tiempo real o solicitudes de origen cruzado; requiere juicio empresarial.
  • Evitar: Alta probabilidad de causar que sitios SPA/dinámicos no se rendericen o no obtengan datos con normalidad, a menos que estés absolutamente seguro de que no necesitas estos recursos.

Ejemplo de Código de Intercepción de Recursos

javascript Copy
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 la intercepción de solicitudes
    await page.setRequestInterception(true);

    // Definir tipos de recursos a bloquear
    const BLOCKED_TYPES = new Set([
        'image',
        'font',
        'media',
        'stylesheet',
    ]);

    // Interceptar solicitudes
    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'});

    // Extraer datos
    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')
es Copy
.then(data => console.log('Resultado de scraping:', data))
    .catch(error => console.error('El scraping falló:', error));

Esquema de Optimización 2: Intercepción de URL de Solicitud

Además de interceptar por tipo de recurso, se puede realizar un control de intercepción más granular en función de las características de la URL. Esto es especialmente efectivo para bloquear anuncios, scripts de análisis y otras solicitudes de terceros innecesarias.

Estrategias de Intercepción de URL

  1. Interceptar por dominio: Bloquear todas las solicitudes de un dominio específico.
  2. Interceptar por ruta: Bloquear solicitudes de una ruta específica.
  3. Interceptar por tipo de archivo: Bloquear archivos con extensiones específicas.
  4. Interceptar por palabra clave: Bloquear solicitudes cuyas URLs contengan palabras clave específicas.

Patrones Comunes de URL Interceptables

Patrón de URL Descripción Ejemplo Recomendación
Servicios de publicidad Dominios de redes publicitarias ad.doubleclick.net, googleadservices.com ⭐ Seguro
Servicios de análisis Scripts de estadísticas y análisis google-analytics.com, hotjar.com ⭐ Seguro
Plugins de redes sociales Botones para compartir en redes, etc. platform.twitter.com, connect.facebook.net ⭐ Seguro
Píxeles de seguimiento Píxeles que rastrean el comportamiento del usuario URLs que contienen pixel, beacon, tracker ⭐ Seguro
Archivos multimedia grandes Archivos de video, audio grandes Extensiones como .mp4, .webm, .mp3 ⭐ Seguro
Servicios de fuentes Servicios de fuentes en línea fonts.googleapis.com, use.typekit.net ⭐ Seguro
Recursos de CDN Recursos de CDN estáticos cdn.jsdelivr.net, unpkg.com ⚠️ Cuidado

Ejemplo de Código de Intercepción de URL

javascript Copy
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 la intercepción de solicitudes
    await page.setRequestInterception(true);

    // Definir dominios y patrones 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 solicitudes
    page.on('request', (request) => {
        const url = request.url();

        // Comprobar dominio
        if (BLOCKED_DOMAINS.some(domain => url.includes(domain))) {
            request.abort();
            console.log(`Dominio bloqueado: ${url.substring(0, 50)}...`);
            return;
        }

        // Comprobar ruta
        if (BLOCKED_PATHS.some(path => url.includes(path))) {
            request.abort();
            console.log(`Ruta bloqueada: ${url.substring(0, 50)}...`);
            return;
        }

        // Permitir otras solicitudes
        request.continue();
    });

    await page.goto(url, {waitUntil: 'domcontentloaded'});

    // Extraer datos
    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 de scraping:', data))
    .catch(error => console.error('El scraping falló:', error));

Esquema de Optimización 3: Simular Dispositivos Móviles

Simular dispositivos móviles es otra estrategia efectiva de optimización del tráfico porque los sitios web móviles suelen proporcionar contenido de página más ligero.

Ventajas de la Simulación de Dispositivos Móviles

  1. Versiones de página más ligeras: Muchos sitios web ofrecen contenido más conciso para dispositivos móviles.
  2. Recursos de imagen más pequeños: Las versiones móviles suelen cargar imágenes más pequeñas.
  3. CSS y JavaScript simplificados: Las versiones móviles suelen utilizar estilos y scripts simplificados.
  4. Reducción de anuncios y contenido no central: Las versiones móviles a menudo eliminan algunas funcionalidades no centrales.
  5. Respuesta adaptativa: Obtener diseños de contenido optimizados para pantallas pequeñas.

Configuración de Simulación de Dispositivos Móviles

Aquí están los parámetros de configuración para varios dispositivos móviles comúnmente utilizados:

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

O usar directamente los métodos incorporados de puppeteer para simular dispositivos móviles.

javascript Copy
import { KnownDevices } from 'puppeteer-core';
const iPhone = KnownDevices['iPhone 15 Pro'];
es Copy
const navegador = await puppeteer.launch();
const pagina = await navegador.newPage();
await pagina.emulate(iPhone);

Ejemplo de Código de Simulación de Dispositivos Móviles

javascript Copy
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 navegador = await puppeteer.connect({
        browserWSEndpoint: scrapelessUrl,
        defaultViewport: null
    });

    const pagina = await navegador.newPage();

    // Establecer simulación de dispositivo móvil
    const iPhone = KnownDevices['iPhone 15 Pro'];
    await pagina.emulate(iPhone);

    await pagina.goto(url, {waitUntil: 'domcontentloaded'});
    // Extraer datos
    const datos = await pagina.evaluate(() => {
        return {
            title: document.title,
            content: document.body.innerText.substring(0, 1000)
        };
    });

    await navegador.close();
    return datos;
}

// Uso
scrapeWithMobileEmulation('https://www.scrapeless.com')
    .then(datos => console.log('Resultado de la recopilación:', datos))
    .catch(error => console.error('La recopilación falló:', error));

Ejemplo de Optimización Integral

Aquí hay un ejemplo integral que combina todos los esquemas de optimización:

javascript Copy
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 recopilación optimizada: ${url}`);

    // Registrar el uso del tráfico
    let totalBytesUsed = 0;

    const navegador = await puppeteer.connect({
        browserWSEndpoint: scrapelessUrl,
        defaultViewport: null
    });

    const pagina = await navegador.newPage();

    // Establecer simulación de dispositivo móvil
    const iPhone = KnownDevices['iPhone 15 Pro'];
    await pagina.emulate(iPhone);

    // Establecer intercepción de solicitudes
    await pagina.setRequestInterception(true);

    // Definir tipos de recursos a bloquear
    const BLOCKED_TYPES = [
        'image',
        'media',
        'font'
    ];

    // Definir dominios a bloquear
    const BLOCKED_DOMAINS = [
        'google-analytics.com',
        'googletagmanager.com',
        'facebook.net',
        'doubleclick.net',
        'adservice.google.com'
    ];

    // Definir rutas URL a bloquear
    const BLOCKED_PATHS = [
        '/ads/',
        '/analytics/',
        '/tracking/'
    ];

    // Interceptar solicitudes
    pagina.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 dominio
        if (BLOCKED_DOMAINS.some(dominio => url.includes(dominio))) {
            console.log(`Dominio bloqueado: ${url.substring(0, 50)}...`);
            request.abort();
            return;
        }

        // Verificar ruta
        if (BLOCKED_PATHS.some(path => url.includes(path))) {
            console.log(`Ruta bloqueada: ${url.substring(0, 50)}...`);
            request.abort();
            return;
        }

        // Permitir otras solicitudes
        request.continue();
    });

    // Monitorear tráfico de red
    pagina.on('response', async (response) => {
        const headers = response.headers();
        const contentLength = headers['content-length'] ? parseInt(headers['content-length'], 10) : 0;
        totalBytesUsed += contentLength;
    });

    await pagina.goto(url, {waitUntil: 'domcontentloaded'});

    // Simular desplazamiento para activar el contenido de carga diferida
    await pagina.evaluate(() => {
        window.scrollBy(0, window.innerHeight);
    });

    await new Promise(resolve => setTimeout(resolve, 1000));

    // Extraer datos
    const datos = await pagina.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
            }))
        };
    });

    // Salida de estadísticas de uso de tráfico
    console.log(`\nEstadísticas de uso de tráfico:`);
    console.log(`Usado: ${(totalBytesUsed / 1024 / 1024).toFixed(2)} MB`);

    await navegador.close();
    return datos;
}

// Uso
optimizedScraping('https://www.scrapeless.com')
    .then(datos => console.log('Recopilación completa:', datos))
    .catch(error => console.error('La recopilación falló:', error));

Comparación de Optimización

Intentamos eliminar el código optimizado del ejemplo integral para comparar el tráfico antes y después de la optimización. Aquí está el código de ejemplo no optimizado:

javascript Copy
import puppeteer from 'puppeteer-core';
javascript Copy
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=tu_clave_api&session_ttl=180&proxy_country=ANY';

async function optimizedScraping(url) {
  console.log(`Iniciando raspado optimizado: ${url}`);

  // Registrar el uso de tráfico
  let totalBytesUsed = 0;

  const browser = await puppeteer.connect({
    browserWSEndpoint: scrapelessUrl,
    defaultViewport: null
  });

  const page = await browser.newPage();

  // Configurar la interceptación de solicitudes
  await page.setRequestInterception(true);

  // Interceptar solicitudes
  page.on('request', (request) => {
    request.continue();
  });

  // Monitorear el tráfico de red
  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 el desplazamiento para activar la carga diferida de contenido
  await page.evaluate(() => {
    window.scrollBy(0, window.innerHeight);
  });

  await new Promise(resolve => setTimeout(resolve, 1000))

  // Extraer datos
  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
      }))
    };
  });

  // Mostrar estadísticas de uso de tráfico
  console.log(`\nEstadísticas de Uso de Tráfico:`);
  console.log(`Usado: ${(totalBytesUsed / 1024 / 1024).toFixed(2)} MB`);

  await browser.close();
  return data;
}

// Uso
optimizedScraping('https://www.scrapeless.com')
  .then(data => console.log('Raspado completo:', data))
  .catch(error => console.error('Raspado fallido:', error));

Después de ejecutar el código no optimizado, podemos ver la diferencia de tráfico de manera muy intuitiva a partir de la información impresa:

Escenario Tráfico Usado (MB) Ratio de Ahorro
No optimizado 6.03
Optimizado 0.81 ≈ 86.6 %

Al combinar los esquemas de optimización anteriores, el consumo de tráfico de proxy puede reducirse significativamente, se puede mejorar la eficiencia del raspado y asegurarse de que se obtenga el contenido central requerido.

En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.

Artículos más populares

Catalogar