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

Puppeteer监控商品按钮的脚本在VSCode调试模式正常,Node.js直接运行时触发TargetCloseError错误

Puppeteer监控商品按钮的脚本在VSCode调试模式正常,Node.js直接运行时触发TargetCloseError错误

看起来你遇到的问题挺典型的——调试模式下脚本能正常跑,但直接用Node执行就会触发TargetCloseError。本质原因是调试时执行速度慢,页面有足够时间完成状态同步;但正常运行时循环重载的节奏太快,导致浏览器页面的CDP会话还没就绪就被强制操作,最终会话被意外关闭。

咱们来调整一下脚本,解决这个问题:

修复后的代码

const puppeteer = require('puppeteer');

(async () => {
  // Launch a new browser instance
  const browser = await puppeteer.launch({ headless: false });
  let page = await browser.newPage();
  
  // URL of the page to load
  const url = 'https://www.bestbuy.com/site/xfx-mercury-amd-radeon-rx-7900-xtx-magnetic-air-24gb-gddr6-pci-express-4-0-gaming-graphics-card-black-red/6588232.p?skuId=6588232';

  // Open the page
  await page.goto(url, { waitUntil: 'networkidle2' });

  // Define the selector for the button you are looking for
  const buttonSelector = '.c-button.c-button-primary.c-button-lg.c-button-block.c-button-icon.c-button-icon-leading.add-to-cart-button';
  
  // 增加最大重试次数,避免无限循环
  const maxRetries = 20;
  let retryCount = 0;

  // Wait for the button to appear or reload the page
  while (retryCount < maxRetries) {
    try {
      // 确保页面未被关闭,如果已关闭则重新创建
      if (page.isClosed()) {
        console.log('Page was closed, creating new page...');
        page = await browser.newPage();
        await page.goto(url, { waitUntil: 'networkidle2' });
      }

      // Try to find the button
      await page.waitForSelector(buttonSelector, { visible: true, timeout: 30000 });
      console.log('Button found!');
      break; // Exit the loop once the button is found
    } catch (error) {
      if (error.name === 'TimeoutError') {
        console.log(`Button not found (retry ${retryCount + 1}/${maxRetries}), reloading the page...`);
        retryCount++;
        
        // 增加短暂等待,避免频繁重载触发反爬
        await page.waitForTimeout(1000);
        // 重载页面,等待网络空闲确保状态稳定
        await page.reload({ waitUntil: 'networkidle2' });
      } else {
        console.log('Unexpected error:', error.message);
        // 针对会话关闭错误,直接重新创建页面
        if (error.message.includes('Session closed')) {
          console.log('Recreating page due to session error...');
          page = await browser.newPage();
          await page.goto(url, { waitUntil: 'networkidle2' });
        }
        retryCount++;
      }
    }
  }

  if (retryCount >= maxRetries) {
    console.log(`Reached max retries (${maxRetries}), stopping...`);
  }
  
  // Close the browser
  await browser.close();
})();

关键修改点说明

  • 增加最大重试次数:避免无限循环给浏览器和目标网站造成压力,也防止脚本意外死循环
  • 页面状态前置检查:在每次尝试前确认页面是否正常打开,若已关闭则重新创建页面,避免在无效资源上执行操作
  • 优化重载逻辑:
    • 重载前增加1秒等待,模拟人类操作节奏,同时避免过于频繁的请求触发反爬机制
    • 重载时使用waitUntil: 'networkidle2',确保页面完全加载、网络稳定后再进行下一轮检查
  • 精细化错误处理:区分超时错误和会话关闭错误,针对不同异常场景做针对性修复,比如会话关闭时直接重建页面
  • 调整等待超时:把waitForSelector的超时从50秒降到30秒,减少会话资源的长期占用

额外注意事项

  • BestBuy有严格的反爬机制,频繁刷新页面可能会被IP封禁,建议把固定等待改成随机延迟(比如await page.waitForTimeout(Math.random() * 2000 + 1000))
  • 可以配合puppeteer-extra和puppeteer-extra-plugin-stealth插件绕过反爬检测,降低被识别为爬虫的概率
  • 电商网站的页面结构可能会随时更新,记得定期检查按钮选择器的有效性

备注:内容来源于stack exchange,提问作者Justin Lin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 09:40:34