优化无头浏览器流量:使用Puppeteer进行高效数据抓取的成本降低策略

概述

使用 Puppeteer 进行数据抓取时,流量消耗是一个重要考虑因素。特别是在使用代理服务时,流量成本可能显著增加。为了优化流量使用,我们可以采用以下策略:

  1. 资源拦截:通过拦截不必要的资源请求来减少流量消耗。
  2. 请求 URL 拦截:根据 URL 特征进一步拦截特定请求以减少流量。
  3. 模拟移动设备:使用移动设备配置获取更轻的页面版本。
  4. 综合优化:结合上述方法以实现最佳效果。

优化方案 1:资源拦截

资源拦截介绍

在 Puppeteer 中,page.setRequestInterception(true) 可以捕捉浏览器发起的每一个网络请求,并决定 继续 (request.continue())、终止 (request.abort()) 或 自定义响应 (request.respond()).

这种方法可以显著减少带宽消耗,特别适合 爬取截图性能优化 场景。

可拦截的资源类型及建议

资源类型 描述 示例 拦截后的影响 推荐级别
image 图像资源 JPG/PNG/GIF/WebP 图像 图像将无法显示 ⭐ 安全
font 字体文件 TTF/WOFF/WOFF2 字体 将使用系统默认字体 ⭐ 安全
media 媒体文件 视频/音频文件 媒体内容无法播放 ⭐ 安全
manifest Web 应用清单 PWA 配置文件 PWA 功能可能受到影响 ⭐ 安全
prefetch 预取资源 <link rel="prefetch"> 对页面影响很小 ⭐ 安全
stylesheet CSS 样式表 外部 CSS 文件 页面样式丢失,可能影响布局 ⚠️ 注意
websocket WebSocket 实时通信连接 实时功能被禁用 ⚠️ 注意
eventsource 服务器发送事件 服务器推送数据 推送功能被禁用 ⚠️ 注意
preflight CORS 预检请求 OPTIONS 请求 跨域请求失败 ⚠️ 注意
script JavaScript 脚本 外部 JS 文件 动态功能被禁用,SPA 可能无法渲染 ❌ 避免
xhr XHR 请求 AJAX 数据请求 无法获取动态数据 ❌ 避免
fetch Fetch 请求 现代 AJAX 请求 无法获取动态数据 ❌ 避免
document 主文档 HTML 页面本身 页面无法加载 ❌ 避免

推荐级别说明:

  • 安全:拦截对数据抓取或首屏渲染几乎没有影响;建议默认拦截。
  • ⚠️ 注意:可能会破坏样式、实时功能或跨域请求;需要根据具体业务进行判断。
  • 避免:高概率会导致 SPA 或动态网站无法正常渲染或获取数据,除非你非常确定不需要这些资源。

资源拦截示例代码

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();

    // 启用请求拦截
    await page.setRequestInterception(true);

    // 定义要拦截的资源类型
    const BLOCKED_TYPES = new Set([
        'image',
        'font',
        'media',
        'stylesheet',
    ]);

    // 拦截请求
    page.on('request', (request) => {
        if (BLOCKED_TYPES.has(request.resourceType())) {
            request.abort();
            console.log(`已拦截: ${request.resourceType()} - ${request.url().substring(0, 50)}...`);
        } else {
            request.continue();
        }
    });

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

    // 提取数据
    const data = await page.evaluate(() => {
        return {
            title: document.title,
            content: document.body.innerText.substring(0, 1000)
        };
    });

    await browser.close();
    return data;
}

// 使用示例
scrapeWithResourceBlocking('https://www.scrapeless.com')

.then(data => console.log('抓取结果:', data))
    .catch(error => console.error('抓取失败:', error));

优化方案 2:请求 URL 拦截

除了按资源类型拦截之外,还可以根据 URL 特征进行更细粒度的拦截控制。这对于阻止广告、分析脚本以及其他不必要的第三方请求特别有效。

URL 拦截策略

  1. 按域名拦截:阻止来自特定域的所有请求
  2. 按路径拦截:阻止来自特定路径的请求
  3. 按文件类型拦截:阻止具有特定扩展名的文件
  4. 按关键词拦截:阻止其 URL 包含特定关键词的请求

常见可拦截 URL 模式

URL 模式 描述 示例 推荐
广告服务 广告网络域名 ad.doubleclick.net, googleadservices.com ⭐ 安全
分析服务 统计和分析脚本 google-analytics.com, hotjar.com ⭐ 安全
社交媒体插件 社交分享按钮等 platform.twitter.com, connect.facebook.net ⭐ 安全
跟踪像素 跟踪用户行为的像素 包含 pixel, beacon, tracker 的 URL ⭐ 安全
大型媒体文件 大型视频、音频文件 扩展名如 .mp4, .webm, .mp3 ⭐ 安全
字体服务 在线字体服务 fonts.googleapis.com, use.typekit.net ⭐ 安全
CDN 资源 静态资源 CDN cdn.jsdelivr.net, unpkg.com ⚠️ 注意

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();

    // 启用请求拦截
    await page.setRequestInterception(true);

    // 定义要拦截的域名和 URL 模式
    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/',
    ];

    // 拦截请求
    page.on('request', (request) => {
        const url = request.url();

        // 检查域名
        if (BLOCKED_DOMAINS.some(domain => url.includes(domain))) {
            request.abort();
            console.log(`拦截域名: ${url.substring(0, 50)}...`);
            return;
        }

        // 检查路径
        if (BLOCKED_PATHS.some(path => url.includes(path))) {
            request.abort();
            console.log(`拦截路径: ${url.substring(0, 50)}...`);
            return;
        }

        // 允许其他请求
        request.continue();
    });

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

    // 提取数据
    const data = await page.evaluate(() => {
        return {
            title: document.title,
            content: document.body.innerText.substring(0, 1000)
        };
    });

    await browser.close();
    return data;
}

// 使用示例
scrapeWithUrlBlocking('https://www.scrapeless.com')
    .then(data => console.log('抓取结果:', data))
    .catch(error => console.error('抓取失败:', error));

优化方案 3:模拟移动设备

模拟移动设备是另一种有效的流量优化策略,因为移动网站通常提供更轻量的页面内容。

移动设备模拟的优势

  1. 更轻量的页面版本:许多网站为移动设备提供更简洁的内容
  2. 更小的图像资源:移动版本通常加载更小的图像
  3. 简化的 CSS 和 JavaScript:移动版本通常使用简化的样式和脚本
  4. 减少广告和非核心内容:移动版本通常移除一些非核心功能
  5. 自适应响应:获取为小屏幕优化的内容布局

移动设备模拟配置

以下是几个常用移动设备的配置参数:

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

或者直接使用 puppeteer 的内置方法模拟移动设备

javascript 复制代码
import { KnownDevices } from 'puppeteer-core';
const iPhone = KnownDevices['iPhone 15 Pro'];
javascript 复制代码
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.emulate(iPhone);
javascript 复制代码
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';

async function optimizedScraping(url) {
  console.log(`开始优化抓取: ${url}`);

  // 记录流量使用
  let totalBytesUsed = 0;

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

  const page = await browser.newPage();

  // 设置请求拦截
  await page.setRequestInterception(true);

  // 拦截请求
  page.on('request', (request) => {
    request.continue();
  });

  // 监控网络流量
  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'});

  // 模拟滚动以触发延迟加载内容
  await page.evaluate(() => {
    window.scrollBy(0, window.innerHeight);
  });

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

  // 提取数据
  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
      }))
    };
  });

  // 输出流量使用统计
  console.log(`\n流量使用统计:`);
  console.log(`已使用: ${(totalBytesUsed / 1024 / 1024).toFixed(2)} MB`);

  await browser.close();
  return data;
}

// 使用
optimizedScraping('https://www.scrapeless.com')
  .then(data => console.log('抓取完成:', data))
  .catch(error => console.error('抓取失败:', error));

在运行未优化的代码后,我们可以从打印的信息中直观地看到流量差异:

场景 使用流量 (MB) 节省比率
未优化 6.03 ---
优化后 0.81 ≈ 86.6 %

通过结合上述优化方案,可以显著减少代理流量消耗,提高抓取效率,并确保获取所需的核心内容。

相关推荐
软件技术NINI11 分钟前
html css js网页制作成品——HTML+CSS+js美甲店网页设计(5页)附源码
javascript·css·html
Luck_ff081017 分钟前
【Python爬虫详解】第四篇:使用解析库提取网页数据——BeautifuSoup
开发语言·爬虫·python
学渣6765625 分钟前
什么时候使用Python 虚拟环境(venv)而不用conda
开发语言·python·conda
悲喜自渡72142 分钟前
线性代数(一些别的应该关注的点)
python·线性代数·机器学习
Huanzhi_Lin1 小时前
python源码打包为可执行的exe文件
python
声声codeGrandMaster2 小时前
django之账号管理功能
数据库·后端·python·django
娃娃略2 小时前
【AI模型学习】双流网络——更强大的网络设计
网络·人工智能·pytorch·python·神经网络·学习
LCY1332 小时前
python 与Redis操作整理
开发语言·redis·python
广西千灵通网络科技有限公司3 小时前
基于Django的个性化股票交易管理系统
后端·python·django
项目題供诗3 小时前
Python类和对象四(十三)
python