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
相关产品推荐
相关产品推荐

