使用Puppeteer获取亚马逊商品页全新商品卖家数量时,点击.olp-text-box选择器报错的问题咨询
.olp-text-box选择器,报错"No node found for selector" 我正尝试用Puppeteer获取亚马逊商品页面中仅售全新商品的卖家数量,但点击第一个按钮选择器.olp-text-box时总是报错:Puppeteer Error: No node found for selector: .olp-text-box。以下是我的代码,希望能得到解决思路:
const pupUrl = 'https://www.amazon.com/dp/' + req.body.asinIdInput; async function configureBrowser(){ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(pupUrl , {waitUntil: 'load', timeout: 0}); await page.click('.olp-text-box'); await page.click('#aod-filter-string'); await page.click('.a-size-base.a-color-base') return page; } async function checkSellers(page){ await page.reload(); let html = await page.evaluate(()=> document.body.innerHTML); $('#aod-filter-offer-count-string',html).each(function(){ var numberOfSellers = $(this).text(); console.log(numberOfSellers); }); } async function monitor(){ let page = await configureBrowser(); await checkSellers(page); } monitor();
遇到这个问题通常是元素加载时机不对、选择器失效或者页面结构更新导致的,下面一步步帮你排查和优化:
1. 先确认选择器是否还有效
亚马逊的页面结构经常迭代,.olp-text-box这个类名可能已经被替换了。你可以手动打开目标商品页面,用浏览器开发者工具(F12)的元素搜索功能,确认这个选择器是否还能定位到"查看其他卖家"的入口。如果找不到,就得重新抓取新的选择器——比如现在亚马逊的卖家入口可能用了#aod-pinned-offer-show-more-button这类新的标识。
2. 优化页面等待策略,确保元素完全加载
你当前用的waitUntil: 'load'只是等待页面基本资源加载完成,但卖家模块这类动态内容可能在load事件之后才渲染。建议换成更稳妥的等待方式:
// 替换原page.goto代码 await page.goto(pupUrl, { waitUntil: 'networkidle2', timeout: 0 }); // 等待目标元素可见后再点击,避免操作过早 await page.waitForSelector('.olp-text-box', { visible: true, timeout: 10000 }); await page.click('.olp-text-box');
networkidle2会等待页面网络请求稳定(只剩2个以内的请求),waitForSelector加visible: true能确保元素不仅存在,还处于可点击状态。
3. 处理亚马逊的反爬机制
亚马逊对爬虫敏感度很高,可能会弹出人机验证、登录提示,或者直接隐藏内容。你可以在代码里加个截图,看看页面实际加载的是什么:
await page.screenshot({ path: 'amazon-check.png' });
如果截图里是验证页面,就得调整浏览器配置,比如设置真实的UA、启用无头模式时加参数:
const browser = await puppeteer.launch({ headless: 'new', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"' ] });
4. 重构checkSellers函数,避免不必要的操作
你代码里的page.reload()完全没必要,反而可能触发反爬;另外不要在Node环境用jQuery解析HTML,直接在浏览器环境操作DOM更可靠:
async function checkSellers(page){ if (!page) return; // 等待卖家数量元素加载完成 await page.waitForSelector('#aod-filter-offer-count-string', { visible: true }); let numberOfSellers = await page.evaluate(() => { const element = document.querySelector('#aod-filter-offer-count-string'); return element ? element.textContent.trim() : '无法获取卖家数量'; }); console.log('仅售全新商品的卖家数量:', numberOfSellers); }
5. 完整优化后的代码示例
const pupUrl = 'https://www.amazon.com/dp/' + req.body.asinIdInput; async function configureBrowser(){ const browser = await puppeteer.launch({ headless: 'new', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"' ] }); const page = await browser.newPage(); 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.goto(pupUrl, { waitUntil: 'networkidle2', timeout: 0 }); // 检查是否遇到人机验证 const hasCaptcha = await page.$('#captchacharacters') !== null; if (hasCaptcha) { console.log('遇到人机验证,请手动处理或添加验证码识别逻辑'); await browser.close(); return null; } // 优先尝试原选择器,失败则用备用选择器 try { await page.waitForSelector('.olp-text-box', { visible: true, timeout: 10000 }); await page.click('.olp-text-box'); } catch (e) { console.log('.olp-text-box找不到,尝试备用选择器'); await page.waitForSelector('#aod-pinned-offer-show-more-button', { visible: true, timeout: 10000 }); await page.click('#aod-pinned-offer-show-more-button'); } // 点击筛选全新商品选项 await page.waitForSelector('#aod-filter-string', { visible: true }); await page.click('#aod-filter-string'); await page.waitForSelector('.a-size-base.a-color-base', { visible: true }); await page.click('.a-size-base.a-color-base'); return page; } async function checkSellers(page){ if (!page) return; await page.waitForSelector('#aod-filter-offer-count-string', { visible: true, timeout: 10000 }); let numberOfSellers = await page.evaluate(() => { const element = document.querySelector('#aod-filter-offer-count-string'); return element ? element.textContent.trim() : '无法获取卖家数量'; }); console.log('仅售全新商品的卖家数量:', numberOfSellers); } async function monitor(){ let page = await configureBrowser(); await checkSellers(page); // 记得关闭浏览器,避免资源泄漏 await page.browser().close(); } monitor();
内容的提问来源于stack exchange,提问作者Timmy




