Puppeteer爬取Twitter用户时间线时滚动停止问题咨询
解决Puppeteer爬取Twitter时间线时滚动卡住无法结束的问题
我看了你的代码,发现几个关键问题导致滚动卡住无法结束,咱们一步步来修正:
原代码里的核心错误
- 错误地在
page.evaluate里调用scrollToEnd:page.evaluate的回调函数是在浏览器的JavaScript环境中运行的,这里根本访问不到Node.js环境里的page对象,也找不到你定义的scrollToEnd函数——这部分逻辑完全不应该放在page.evaluate里面,直接在Node端调用就行。 waitForFunction的表达式没有动态更新:你用模板字符串写的document.body.scrollHeight > ${previousHeight},这个表达式里的previousHeight是第一次赋值的0,之后循环里更新previousHeight时,这个字符串不会重新生成,导致waitForFunction一直等待的是document.body.scrollHeight > 0(这永远为真)。当滚动到底部后,scrollHeight不再变化,这个函数就会无限等待下去,不会触发结束条件。- 没有设置超时时间:默认情况下
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
相关产品推荐
相关产品推荐

