¿Cómo optimizar el uso de tráfico de tu navegador al máximo?
Senior Web Scraping Engineer
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:
- Intercepción de recursos: Reducir el consumo de tráfico interceptando solicitudes de recursos innecesarias.
- 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.
- Simular dispositivos móviles: Usar configuraciones de dispositivos móviles para obtener versiones más ligeras de las páginas.
- 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
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
.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
- Interceptar por dominio: Bloquear todas las solicitudes de un dominio específico.
- Interceptar por ruta: Bloquear solicitudes de una ruta específica.
- Interceptar por tipo de archivo: Bloquear archivos con extensiones específicas.
- 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
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
- Versiones de página más ligeras: Muchos sitios web ofrecen contenido más conciso para dispositivos móviles.
- Recursos de imagen más pequeños: Las versiones móviles suelen cargar imágenes más pequeñas.
- CSS y JavaScript simplificados: Las versiones móviles suelen utilizar estilos y scripts simplificados.
- Reducción de anuncios y contenido no central: Las versiones móviles a menudo eliminan algunas funcionalidades no centrales.
- 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
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
import { KnownDevices } from 'puppeteer-core';
const iPhone = KnownDevices['iPhone 15 Pro'];
es
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
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
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
import puppeteer from 'puppeteer-core';
javascript
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.



