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

Puppeteer中page.evaluate内setTimeout未触发的滚动加载问题

解决Puppeteer中page.evaluate内递归滚动失效的问题

问题核心是:page.evaluate 不会自动等待内部的异步递归操作完成,原脚本里的setTimeout属于浏览器端异步任务,Node端的Puppeteer在执行完初始的scroll_page调用后,就认为page.evaluate执行完毕,直接继续后续逻辑,导致递归被"忽略"。

正确实现方式:返回Promise让Puppeteer等待递归完成

把滚动逻辑封装成返回Promise的函数,让page.evaluate返回这个Promise,Puppeteer会等待Promise resolve后再继续执行后续代码。同时可以优化终止条件,用页面滚动位置代替调试用的safety参数,更精准:

await page.evaluate(async () => {
  return new Promise((resolve) => {
    const scrollStep = 500;
    const loadWaitTime = 1250;

    function scrollPage() {
      // 判断是否已滚动到页面底部(留100px误差兼容动态加载)
      const isAtBottom = window.innerHeight + window.scrollY >= document.body.scrollHeight - 100;
      if (isAtBottom) {
        resolve();
        return;
      }
      // 执行滚动
      window.scrollBy(0, scrollStep);
      // 递归调用
      setTimeout(scrollPage, loadWaitTime);
    }

    scrollPage();
  });
});

关键说明

  1. Promise封装:通过返回Promise,明确告诉Puppeteer需要等待整个滚动流程结束,而非执行完初始调用就终止page.evaluate。
  2. 滚动终止条件:用页面滚动位置判断是否到底,比固定safety次数更可靠,适配动态加载内容的场景。
  3. 等待时间调整:loadWaitTime可根据页面懒加载的实际速度调整,确保每次滚动后图片有足够时间加载。

保留safety参数的调试版本

如果需要保留safety参数防止无限循环,可修改为:

await page.evaluate(async () => {
  return new Promise((resolve) => {
    const scrollStep = 500;
    const loadWaitTime = 1250;
    let safety = 100; // 调试用安全次数

    function scrollPage() {
      const isAtBottom = window.innerHeight + window.scrollY >= document.body.scrollHeight - 100;
      if (safety <= 0 || isAtBottom) {
        resolve();
        return;
      }
      window.scrollBy(0, scrollStep);
      safety--;
      setTimeout(scrollPage, loadWaitTime);
    }

    scrollPage();
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:52:35