【问题标题】:Puppeteer: Scrolling down twitter timeline stopsPuppeteer:向下滚动推特时间线停止
【发布时间】:2019-03-09 03:35:15
【问题描述】:

我在使用 puppeteer 抓取用户时间线上的所有推文 URL 时遇到问题。

对于 puppeteer,脚本应该在 scrollToEnd 函数中的 while 循环的每次迭代中向下滚动时间线,直到它到达底部。为了监控进度,我让脚本输出了previousHeight 变量的值,即每次执行滚动前评估的document.body 的当前scrollheight

但是,一旦输出值变为 285,834,滚动就会停止。令人费解的是,脚本既没有跳出while循环,也没有page.waitForFunction方法抛出超时错误。

我应该如何重写scrollToEnd 函数或脚本的任何其他部分,以便函数正确结束?

这是我的代码的 sn-p。为简洁起见,省略了不相关的功能。

const puppeteer = require('puppeteer');

var UserUrls = ['https://twitter.com/someuser'];

// more functions here

async function scrollToEnd(
    page,
    ScrollDelay = 1000
) {
    try {
        let previousHeight = 0;
        let notEnd = await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
        while (notEnd) {
            previousHeight = await page.evaluate('document.body.scrollHeight');
            await page.evaluate('window.scrollBy(0, document.body.scrollHeight)');
            await page.waitFor(ScrollDelay);

            notEnd = await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`);
            console.log(previousHeight)
        };
        return;
    } catch (e) {
        return;
    };
};

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    var tweetUrls = [];
    for (let UserUrl of UserUrls) {
        await page.goto(UserUrl);
        await page.evaluate((async () => {
            await scrollToEnd(page);
        })());
        await page.screenshot({ path: 'PageEnd.png' });
        tweetUrls = await getTweetUrls(page, extractItems, 100);
    };
    await browser.close();
    console.log(tweetUrls);
})();

【问题讨论】:

    标签: javascript node.js twitter web-scraping puppeteer


    【解决方案1】:

    您可以尝试这两种方法中的一种吗?此脚本尝试通过比较滚动高度(如您所做的那样)或等待标记流结束的元素可见来滚动到底部。所有滚动逻辑都放置在浏览器上下文中评估的函数中。这两个函数都返回整个页面中的推文计数,以将结果与时间线顶部声明的用户推文计数进行比较。另外,我已将第一种方法的延迟更改为 3 秒,因为有时 1 秒对于更改滚动高度来说似乎太小了。

    'use strict';
    
    const puppeteer = require('puppeteer');
    
    (async function main() {
      try {
        const browser = await puppeteer.launch({ headless: false });
        const [page] = await browser.pages();
    
        await page.goto('https://twitter.com/GHchangelog');
        const data1 = await page.evaluate(scrollToBottomByMaxHeight);
        console.log(`Tweets: ${data1}`);
    
        await page.goto('https://twitter.com/GHchangelog');
        const data2 = await page.evaluate(scrollToBottomByEndElement);
        console.log(`Tweets: ${data2}`);
    
        // await browser.close();
      } catch (err) {
        console.error(err);
      }
    })();
    
    async function scrollToBottomByMaxHeight() {
      try {
        let previousHeight = 0;
        let currentHeight = document.scrollingElement.scrollHeight;
    
        while (previousHeight < currentHeight) {
          previousHeight = document.scrollingElement.scrollHeight;
          window.scrollBy(0, previousHeight);
          await new Promise((resolve) => { setTimeout(resolve, 3000); });
          currentHeight = document.scrollingElement.scrollHeight;
        }
    
        return document.querySelectorAll('a.js-permalink').length;
      } catch (err) {
        return err;
      }
    }
    
    async function scrollToBottomByEndElement() {
      try {
        const endElement = document.querySelector('div.stream-end');
    
        while (endElement.clientHeight === 0) {
          window.scrollBy(0, document.scrollingElement.scrollHeight);
          await new Promise((resolve) => { setTimeout(resolve, 1000); });
        }
    
        return document.querySelectorAll('a.js-permalink').length;
      } catch (err) {
        return err;
      }
    }
    

    【讨论】:

    • scrollToBottomByMaxHeight 函数返回 40 而 scrollToBottomByEndElement 函数返回 186。我是否可以得出结论,后者是一种更可靠的方法,因为 clientHeight 应该保持在 0 直到 div.stream-end 元素加载了吗?
    • @figment 我一直有 186 个,但似乎第一种方法更脆弱,因为它取决于网络响应能力(您可以尝试将延迟增加到 10 秒以查看是否有变化) .所以我认为,是的,第二种方法更可靠。
    • @figment div.stream-end 已经在初始页面状态加载,它只是隐藏到流的末尾,直到那时它的clientHeight 为0。
    猜你喜欢
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多