Puppeteer中page.evaluate()方法执行异常,无法返回预期爬虫结果求助
问题诊断与解决方案
我帮你拆解下这个问题的核心原因,以及对应的修复方案:
1. 冗余代码引发的逻辑干扰
你在page.evaluate()里写了这两行:
var classCode = window[$(item).closest("tr").find(">:nth-child(1)").text()] classCode = {};
第一行完全是无用代码——你试图把课程代码当作全局变量从window对象里获取,这显然不存在,而且紧接着第二行就把classCode重新初始化为空对象。虽然这行没直接导致返回空数组,但它会干扰调试思路,建议直接删除。
2. 页面等待策略不够严谨
你用了waitUntil: 'domcontentloaded',但有时候页面的表格数据可能在DOM加载完成后还需要一点时间渲染。建议把导航等待改成networkidle2(等待网络连接数降到2以下,意味着大部分资源加载完成),并且在执行page.evaluate()之前,明确等待目标元素出现:
await page.waitForSelector("td:contains('Lec')", { timeout: 10000 });
这样能确保你要抓取的元素已经完全渲染在页面上,避免因元素未加载导致的空数组问题。
3. jQuery引入的可靠性问题
你用本地的jquery.js文件引入,如果文件路径不对或者文件缺失,会导致page.evaluate()里的jQuery代码无法运行。建议改用CDN链接引入jQuery,更稳定:
await page.addScriptTag({ url: 'https://code.jquery.com/jquery-3.7.1.min.js' });
4. console.log的输出位置误解
page.evaluate()内部的console.log()是在浏览器的上下文里执行的,所以输出只会出现在Puppeteer控制的浏览器的开发者工具控制台里,不会出现在Node.js的终端。这就是为什么你偶尔能在浏览器里看到输出,但Node终端看不到的原因。如果要在Node终端打印page.evaluate()里的内容,需要把数据返回出来,或者用page.on('console')监听浏览器的console事件。
修正后的完整代码
const puppeteer = require('puppeteer'); (async () => { let url = 'https://www.reg.uci.edu/perl/WebSoc'; let browser = await puppeteer.launch({ headless: false }); let page = await browser.newPage(); // 监听浏览器console,把输出同步到Node终端 page.on('console', msg => console.log('Browser Console:', msg.text())); await page.goto(url, { waitUntil: 'domcontentloaded' }); await page.select('select[name=Dept]', 'BIO SCI'); await page.click('input[value="Display Web Results"]'); // 改用networkidle2等待页面加载完成 await page.waitForNavigation({ waitUntil: 'networkidle2' }); // 用CDN引入jQuery await page.addScriptTag({ url: 'https://code.jquery.com/jquery-3.7.1.min.js' }); // 等待目标元素出现,确保渲染完成 await page.waitForSelector("td:contains('Lec')", { timeout: 10000 }); var biologyClasses = await page.evaluate(() => { var classes = $("td:contains('Lec')") .not('.Comments') .not('.Pct100'); var classesArray = Array.from(classes); console.log('Found Lec elements:', classesArray.length); // 会在Node终端显示,因为我们监听了console var biology = []; classesArray.forEach(function(item) { var classRow = $(item).closest("tr"); var classCode = {}; // 可选:加上课程代码字段,让数据更完整 classCode.courseCode = classRow.find(">:nth-child(1)").text().trim(); classCode.instructor = classRow.find(">:nth-child(5)").text().trim(); biology.push(classCode); }); return biology; }); console.log('Final Biology Classes:', biologyClasses); // 记得关闭浏览器(可选) // await browser.close(); })();
额外说明
- 我加了
page.on('console')监听,这样浏览器里的console.log会同步到Node终端,方便调试。 - 给文本内容加了
.trim(),避免多余的空格干扰数据。 - 可选添加课程代码字段,让返回的数据更完整。
内容的提问来源于stack exchange,提问作者Daniel-G
相关产品推荐
相关产品推荐

