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(); }); });
关键说明
- Promise封装:通过返回Promise,明确告诉Puppeteer需要等待整个滚动流程结束,而非执行完初始调用就终止
page.evaluate。 - 滚动终止条件:用页面滚动位置判断是否到底,比固定
safety次数更可靠,适配动态加载内容的场景。 - 等待时间调整:
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
相关产品推荐
相关产品推荐

