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

Node.js网页爬取:Puppeteer无法获取亚马逊页面全部ul元素求助

问题描述

我尝试爬取印度亚马逊的产品页面:https://www.amazon.in/gp/browse.html?node=4092115031&ref_=nav_em_sbc_tvelec_gaming_consoles_0_2_9_12,页面内的产品列表位于ul标签中(每行5个产品)。但运行代码定位所有ul标签时,终端仅显示少量ul,产品相关的ul完全未出现;即使定位整个body,也无法获取完整页面内容。曾尝试使用waitForSelector但无效,哪怕无需滚动加载产品,至少也应显示部分产品ul列表。

我的代码如下:

const puppeteer = require("puppeteer");

const amazonURL =
  "https://www.amazon.in/gp/browse.html?node=4092115031&ref_=nav_em_sbc_tvelec_gaming_consoles_0_2_9_12";

async function run(params) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.setUserAgent(
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.3"
  );

  await page.goto(amazonURL);

  const products = await page.evaluate(() => document.querySelectorAll("ul"));
  console.log(products);

  await browser.close();
}

run();

我想先解决定位ul的问题,之后再提取标题、价格和图片,请问该如何解决?


解决方案

1. 核心问题:DOM元素无法跨上下文传递

page.evaluate中返回的document.querySelectorAll("ul")是浏览器上下文的DOM元素集合,这些对象无法直接序列化传递到Node.js环境,所以你看到的只是空的对象引用,而非实际元素内容。必须在浏览器上下文内提取可序列化的信息(如类名、文本内容、元素数量等)后再返回。

2. 应对亚马逊反爬机制

亚马逊会针对无头浏览器做检测,仅设置User-Agent不够,需要额外配置模拟真实浏览器行为:

  • 使用新版无头模式,更难被识别
  • 设置合理的视口和窗口大小
  • 等待网络空闲确保动态内容加载完成
  • 延长超时时间避免网络波动导致失败

3. 修正后的代码

const puppeteer = require("puppeteer");

const amazonURL =
  "https://www.amazon.in/gp/browse.html?node=4092115031&ref_=nav_em_sbc_tvelec_gaming_consoles_0_2_9_12";

async function run() {
  const browser = await puppeteer.launch({
    headless: "new",
    args: ["--start-maximized"]
  });
  const page = await browser.newPage();

  // 设置现代浏览器UA
  await page.setUserAgent(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
  );
  
  // 设置视口模拟真实屏幕
  await page.setViewport({ width: 1920, height: 1080 });

  // 确保JS启用(亚马逊依赖JS渲染内容)
  await page.setJavaScriptEnabled(true);

  // 导航并等待网络空闲,确保内容加载完成
  await page.goto(amazonURL, {
    waitUntil: "networkidle2",
    timeout: 60000
  });

  // 等待产品列表的ul加载完成(用亚马逊产品列表的特定选择器)
  await page.waitForSelector("ul.s-result-list", { timeout: 30000 });

  // 提取所有ul的关键信息
  const ulInfo = await page.evaluate(() => {
    const uls = Array.from(document.querySelectorAll("ul"));
    return uls.map((ul, index) => ({
      index,
      className: ul.className,
      childCount: ul.children.length,
      isProductList: ul.classList.contains("s-result-list"),
      productCount: ul.classList.contains("s-result-list") ? ul.children.length : 0
    }));
  });

  console.log("所有UL信息:", ulInfo);
  
  // 示例:提取产品列表的标题和价格
  const productList = await page.evaluate(() => {
    const productItems = Array.from(document.querySelectorAll("ul.s-result-list li"));
    return productItems.map(item => ({
      title: item.querySelector("h2 a span")?.textContent.trim() || "无标题",
      price: item.querySelector(".a-price .a-offscreen")?.textContent.trim() || "无价格"
    }));
  });

  console.log("产品列表:", productList);

  await browser.close();
}

run();

关键修改说明

  • 无头模式优化:headless: "new"是Puppeteer新版无头模式,行为更接近真实浏览器,降低被检测概率;--start-maximized避免响应式布局导致元素结构变化。
  • 等待策略调整:networkidle2等待网络空闲2秒,确保动态渲染的产品列表加载完成;waitForSelector明确等待产品列表的ul出现,避免提前执行提取逻辑。
  • 数据提取方式:在浏览器上下文内将DOM元素转换为可序列化的对象(如包含类名、子元素数量的对象),再传递到Node.js环境打印。
  • 反爬增强:更新User-Agent到最新版本,设置合理视口,确保JS启用,这些配置能有效降低亚马逊的拦截概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:34:52