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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:32:42