Puppeteer循环调用scrollIntoView()实现无限加载页面爬取20条帖子问题
问题修复方案
出错原因
page.evaluate执行时不会等待内部异步的setTimeout回调完成就会返回,所以你的循环会在极短时间内跑完20次,滚动逻辑还没触发整个流程就已经结束了- 无限滚动页面滚动到对应位置后,需要等待接口返回数据、新元素渲染完成才能继续操作,原逻辑没有做对应的等待处理
- 原逻辑每次都按固定索引取元素,新内容加载后列表长度会变化,容易出现索引不匹配取不到元素的问题
可用代码实现
const selector = 'div[role="feed"]:nth-child(2) div.sjgh65i0' // 先等第一屏的元素加载完成 await page.waitForSelector(selector) for (let i = 0; i < 20; i++) { // 每次循环先获取当前已经渲染的所有帖子元素 const elements = await page.$$(selector) // 如果当前索引超出已有元素长度,说明需要等新内容加载 if (!elements[i]) { // 等待新元素渲染出来,最多等5秒避免卡死 await page.waitForFunction( (selector, targetCount) => document.querySelectorAll(selector).length >= targetCount, { timeout: 5000 }, selector, i + 1 ) } // 滚动到当前要处理的元素位置 await elements[i].scrollIntoView() // 等待滚动完成+内容渲染,可根据页面加载速度调整等待时长 await page.waitForTimeout(1000) // 这里添加你抓取当前帖子内容的逻辑 // const postContent = await elements[i].$eval('.xxx', el => el.innerText) }
补充说明
- 如果页面滚动后加载新内容的速度慢,可以适当调大
waitForTimeout的等待时长 - 如果你只需要滚动加载20条不需要单独处理每条,也可以改成每次滚动到列表最后一个元素,直到列表长度达到20即可
内容的提问来源于stack exchange,提问作者fanonano
相关产品推荐
相关产品推荐

