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

将Chrome控制台Script A适配为Puppeteer脚本:Script C存明显问题吗?

排查你的Puppeteer脚本(Script C)的明显问题

Hey Roger, let's walk through the obvious issues in your Script C and fix them step by step:

1. 混淆的变量命名(非致命但影响可读性)

你用hotelData来存储价格相关的结果——这只是可读性问题,不是bug,但把它重命名为priceResults这类贴合场景的名字,后续维护代码会更轻松。

2. page.evaluate内的console.log不会在终端输出

page.evaluate的代码运行在浏览器上下文里,而非你的Node.js终端环境。这里的console.log只会出现在浏览器开发者工具中(无头模式下看不到)。正确的做法是把需要的数据从page.evaluate里return出来,再在Node.js环境里打印。

3. 未处理空结果的情况(可能导致崩溃)

如果过滤/排序逻辑返回的priceRecordsSortedByFontSize是空数组,直接访问priceRecordsSortedByFontSize[0]会抛出Cannot read properties of undefined错误。必须添加防御性判断。

4. 页面可能未完全加载

page.goto默认只等待DOM就绪,但电商网站的价格往往是动态加载的。添加waitUntil: 'networkidle2'或等待特定元素,能确保价格渲染完成后再开始抓取。

5. puppeteer-core的路径注意事项

puppeteer-core不自带Chromium,所以你必须指定正确的executablePath。你用的/usr/bin/chromium-browser在Linux环境下是合理的,但如果启动失败,一定要检查路径是否匹配你的系统。


修复后的Script C版本

const puppeteer = require('puppeteer-core');
let targetUrl = 'https://shop.coles.com.au/a/dianella/product/moccona-coffee-capsules-espresso-7';

(async () => {
  try {
    const browser = await puppeteer.launch({ 
      executablePath: '/usr/bin/chromium-browser', 
      headless: true,
      // 解决Linux环境下可能出现的沙箱问题
      args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    const page = await browser.newPage();
    await page.setViewport({ width: 1920, height: 926 });
    
    // 等待网络空闲,确保动态内容加载完成
    await page.goto(targetUrl, { waitUntil: 'networkidle2' });

    // 从page.evaluate返回数据,而非在内部打印
    let priceResults = await page.evaluate(() => {
      let elements = [ ...document.querySelectorAll('body *') ]
      
      function createRecordFromElement(element) {
        const text = element.textContent.trim()
        const record = {}
        const bBox = element.getBoundingClientRect()
        
        if(text.length <= 30 && !(bBox.x === 0 && bBox.y === 0)) {
          record.fontSize = parseInt(getComputedStyle(element).fontSize)
        }
        
        record.y = bBox.y
        record.x = bBox.x
        record.text = text
        return record
      }

      let records = elements.map(createRecordFromElement)
      
      function canBePrice(record) {
        if( record.y > 600 || record.fontSize === undefined || !record.text.match(/(^(US ){0,1}(rs\.|Rs\.|RS\.|\$|₹|INR|USD|CAD|C\$){0,1}(\s){0,1}[\d,]+(\.\d+){0,1}(\s){0,1}(AED){0,1}$)/) ) {
          return false
        } else {
          return true
        }
      }

      let possiblePriceRecords = records.filter(canBePrice)
      
      let priceRecordsSortedByFontSize = possiblePriceRecords.sort((a, b) => {
        if (a.fontSize === b.fontSize) {
          return a.y - b.y; // 用数值比较替代布尔值,排序更可靠
        }
        return b.fontSize - a.fontSize; // 倒序排列,字号大的在前
      })

      // 返回前2个价格(如果没有结果则返回空数组)
      return priceRecordsSortedByFontSize.slice(0,2).map(record => record.text);
    });

    // 在Node.js环境打印结果
    console.log("找到的最高优先级价格:");
    priceResults.forEach((price, index) => {
      console.log(`${index + 1}: ${price}`);
    });

    await browser.close();
  } catch (error) {
    // 捕获并打印运行时错误(比如浏览器启动失败、页面加载异常)
    console.error("脚本运行出错:", error);
  }
})();

关键修改说明

  • 添加try/catch块捕获并记录所有运行时错误,方便排查问题
  • 重命名bookingUrl为targetUrl、hotelData为priceResults,让语义更清晰
  • 修改排序函数为数值减法,避免布尔值排序的潜在问题
  • 从page.evaluate返回结果,在Node.js环境打印
  • 给page.goto添加waitUntil: 'networkidle2',确保动态价格加载完成
  • 添加Linux环境下的沙箱禁用参数,解决常见的无头Chromium启动问题
  • 用slice(0,2)替代直接访问下标,避免空数组导致的崩溃

内容的提问来源于stack exchange,提问作者Roger D.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:29:08