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

