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

Puppeteer爬取Twitter用户时间线时滚动停止问题咨询

解决Puppeteer爬取Twitter时间线时滚动卡住无法结束的问题

我看了你的代码,发现几个关键问题导致滚动卡住无法结束,咱们一步步来修正:

原代码里的核心错误

  1. 错误地在page.evaluate里调用scrollToEnd:page.evaluate的回调函数是在浏览器的JavaScript环境中运行的,这里根本访问不到Node.js环境里的page对象,也找不到你定义的scrollToEnd函数——这部分逻辑完全不应该放在page.evaluate里面,直接在Node端调用就行。
  2. waitForFunction的表达式没有动态更新:你用模板字符串写的document.body.scrollHeight > ${previousHeight},这个表达式里的previousHeight是第一次赋值的0,之后循环里更新previousHeight时,这个字符串不会重新生成,导致waitForFunction一直等待的是document.body.scrollHeight > 0(这永远为真)。当滚动到底部后,scrollHeight不再变化,这个函数就会无限等待下去,不会触发结束条件。
  3. 没有设置超时时间:默认情况下waitForFunction超时时间很长,即使卡住也不会立刻抛出错误,加上你的catch块直接return,导致你看不到错误,误以为脚本没反应。

修正后的scrollToEnd函数

我重写了这个函数,解决了上面的问题,还增加了超时判断来识别到底部的情况:

async function scrollToEnd(page, scrollDelay = 1500) {
  try {
    let previousHeight = await page.evaluate('document.body.scrollHeight');
    
    while (true) {
      // 滚动到当前页面底部
      await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
      
      try {
        // 等待新内容加载,设置5秒超时——如果5秒内scrollHeight没变化,就认为到底了
        await page.waitForFunction(
          `document.body.scrollHeight > ${previousHeight}`,
          { timeout: 5000 }
        );
        // 更新高度,准备下一轮滚动
        previousHeight = await page.evaluate('document.body.scrollHeight');
        console.log(`当前滚动高度: ${previousHeight}`);
      } catch (e) {
        // 超时说明没有新内容加载了,退出循环
        console.log("已滚动到时间线底部,结束滚动");
        break;
      }
      
      // 给页面一点时间加载内容,Twitter反爬严,建议把延迟调长一点或者用随机值
      await page.waitForTimeout(scrollDelay);
    }
  } catch (e) {
    console.error("滚动过程中出现异常:", e);
  }
}

修正主函数里的调用错误

把原来在page.evaluate里的调用改成直接调用scrollToEnd,同时建议加上waitUntil: 'networkidle2'确保页面初始加载完成:

(async () => {
  const browser = await puppeteer.launch({ headless: false }); // 关闭无头模式方便调试
  const page = await browser.newPage();
  var tweetUrls = [];
  const UserUrls = ['https://twitter.com/someuser'];
  
  for (let UserUrl of UserUrls) {
    // 等待网络空闲再开始操作,确保页面初始内容加载完成
    await page.goto(UserUrl, { waitUntil: 'networkidle2' });
    // 直接调用滚动函数,不要放在page.evaluate里!
    await scrollToEnd(page);
    await page.screenshot({ path: 'PageEnd.png' });
    tweetUrls = await getTweetUrls(page, extractItems, 100);
  }
  
  await browser.close();
  console.log(tweetUrls);
})();

额外的注意事项

  • Twitter反爬机制:频繁滚动很容易被限制,建议把scrollDelay调长到1500-3000ms,或者用随机延迟(比如Math.random() * 1000 + 1500),避免被暂时限制访问。
  • 更可靠的结束判断:有时候scrollHeight可能因为页面其他元素变化而改变,但没有新推文。你可以改成等待新的推文元素出现(比如用page.waitForSelector等待某个推文的选择器,超时则认为到底),这样判断更准确。
  • 避免内存泄漏:如果爬取大量用户,建议每次爬完一个用户后关闭当前页面,重新打开新页面,避免内存占用过高。

内容的提问来源于stack exchange,提问作者figment

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:27:10