You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Node.js爬虫代码实现仅抓取可视商品信息?

解决方案

要实现仅抓取可视区域内的商品,核心是在浏览器上下文里判断元素是否处于可视范围,同时修正原代码的滚动与数据抓取逻辑,以下是修改后的完整代码:

const puppeteer = require('puppeteer');

// 存储已抓取的商品标题,避免重复打印
const scrapedTitles = new Set();

(async () => {
  const browser = await puppeteer.launch({
    headless: false
  });
  
  const page = await browser.newPage();
  // 设置视口大小,模拟真实浏览器可视区域
  await page.setViewport({ width: 1200, height: 800 });

  await page.goto('https://www.balenciaga.com/en-us/women/shoes/sneakers', { waitUntil: 'networkidle2' });
  
  // 先抓取初始可视区域的商品
  await getVisibleData(page);
  // 开始滚动加载并抓取
  await scrollAndScrape(page);
})();

// 滚动页面并等待新内容加载
const scrollAndScrape = async (page) => {
  let previousHeight = await page.evaluate('document.body.scrollHeight');
  
  while (true) {
    // 滚动到页面底部
    await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
    // 等待新内容加载(可根据页面加载速度调整时间)
    await page.waitForTimeout(2000);
    
    // 抓取当前可视区域的商品
    await getVisibleData(page);
    
    // 检查是否已经滚动到页面底部
    const currentHeight = await page.evaluate('document.body.scrollHeight');
    if (currentHeight === previousHeight) {
      console.log('已滚动到页面底部,停止抓取');
      break;
    }
    previousHeight = currentHeight;
  }
};

// 抓取当前可视区域内的商品
const getVisibleData = async (page) => {
  const visibleProducts = await page.evaluate(() => {
    // 判断元素是否在可视区域内的工具函数
    const isElementVisible = (el) => {
      const rect = el.getBoundingClientRect();
      return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
      );
    };
    
    const products = [];
    // 获取所有商品元素
    const items = document.querySelectorAll('.l-productgrid__item .c-product__infos');
    
    items.forEach(item => {
      if (isElementVisible(item)) {
        const title = item.querySelector('h2').textContent.trim();
        const price = item.querySelector('p').textContent.trim();
        products.push({ title, price });
      }
    });
    
    return products;
  });
  
  // 过滤已抓取过的商品,避免重复打印
  const newProducts = visibleProducts.filter(p => !scrapedTitles.has(p.title));
  
  // 打印新抓取的商品
  newProducts.forEach((res, i) => {
    scrapedTitles.add(res.title);
    console.log(`${scrapedTitles.size} 名稱: ${res.title}, 價錢: ${res.price}`);
  });
};

关键修改点说明

  • 移除Cheerio依赖:Cheerio基于静态DOM解析,无法判断元素是否在可视区域,直接在page.evaluate中操作浏览器上下文的DOM,才能准确判断可视性。
  • 可视区域判断函数:通过getBoundingClientRect()获取元素的位置信息,对比浏览器视口的宽高,判断元素是否完全处于可视范围内(也可根据需求调整为部分可见即抓取)。
  • 滚动逻辑优化:使用循环滚动替代递归调用,添加滚动终止条件(当页面高度不再变化时,说明已到底部),避免无限递归。
  • 去重处理:用Set存储已抓取的商品标题,避免滚动时重复打印之前已抓取过的商品。
  • 视口设置:初始化时设置浏览器视口大小,模拟真实用户的可视区域,确保判断逻辑准确。

内容的提问来源于stack exchange,提问作者Caramel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:54:41