Twitter Automation - Puppeteer - 获取推文的用户句柄 - 如何优化此循环以在每次迭代时有效地检查三个条件?

问题描述 投票:0回答:0

我正在尝试使用 puppeteer 和 snscrape 获取推文。

我希望它如何运作:

首先,我使用 snscrape 抓取推文 URL 和用户名,并将它们作为数组存储在 JSON 文件中,如下所示👇

[["https://twitter.com/NikkiSiapno/status/1595712124222857217", "NikkiSiapno"],  ["https://twitter.com/NikkiSiapno/status/1559472755443220481", "NikkiSiapno"]] 

在此之后,我想使用 Puppeteer 逐一遍历每个 URL,提取每条推文的文本内容,并在满足以下条件的情况下按顺序将它们打印到控制台:

  • 检查标题以确定它是推文还是主题。如果是推文,只提取第一条推文。

  • 如果是线程,检查前n条推文的用户句柄是否与tweets.json文件中存储的用户句柄匹配。如果匹配,提取他们的文本内容。

  • 在线程中,它不应该捕获其他用户的回复,而只能捕获作者的推文。为此,它应该评估线程中的前 30 条推文(因为作者的推文在顶部),将它们的用户句柄与存储在 JSON 文件中的用户句柄进行比较,如果匹配则提取文本内容。

问题:

  • 我不知道如何提取每条推文的用户句柄,同时在每次迭代中将其与 authorName 变量中的用户句柄进行比较。

  • 我不确定如何正确控制滚动以避免跳过线程中的某些推文。

任何帮助将不胜感激。另外,我们如何优化这段代码?

const puppeteer = require("puppeteer");
(async () => {
 const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: false,
 });
 const page = await browser.newPage();
 const tweetUrls = require("./tweets.json");
 for (let i = 0; i < tweetUrls.length; i++) {
 const tweetUrl = tweetUrls[i][0];
 const authorName = tweetUrls[i][1];
 await page.goto(tweetUrl, { waitUntil: "networkidle0" });

 // Wait for the tweets to load
 await page.waitForSelector('[data-testid="tweet"]');
 // Wait for the sheetDialog element and close it.
 await page.waitForSelector('div[data-testid="sheetDialog"]');
 await page.click('div[data-testid="app-bar-close"]');

 // extract the heading title
 const tweetHeading = await page.$('h2[role="heading"]');
 const tweetHeadingText = await page.evaluate(
 (el) => el.querySelector("span").textContent,
      tweetHeading
 );

// if the heading title is "Thread" execute this:
 if (tweetHeadingText === "Thread") {
 // extract the user handle
 const Handle = await page.$('div[data-testid="User-Names"]');
 const userHandle = await page.evaluate((el) => el.querySelector("a > div > span").textContent.substring(1),Handle
 );
 const tweetTextSet = new Set();
 let tweetCount = 0;
 // For the first n tweets, while the userHandle === authorName grab their text content.
 while (tweetCount < 30 && userHandle === authorName) {
 const tweetEls = await page.$$('[data-testid="tweetText"]');
 for (const tweetEl of tweetEls) {
 const tweetText = await page.evaluate(
 (el) => el.textContent.trim(),
                  tweetEl
 );
 if (!tweetTextSet.has(tweetText)) {
                  console.log(tweetText);
                  tweetTextSet.add(tweetText);
                  tweetCount++;
 if (tweetCount >= 40) {
 break;
 }
 }
 }
 await page.evaluate(() => {
                window.scrollBy(0, window.innerHeight);
 });
 await new Promise((resolve) => setTimeout(resolve, 1000));
 }
// if the heading title is "Tweet" then only get the first tweet:
 } else if (tweetHeadingText === "Tweet") {
 const tweetEls = await page.$$('[data-testid="tweetText"]');
 const firstTweetEl = tweetEls[0];
 const firstTweetText = await page.evaluate(
 (el) => el.textContent.trim(),
              firstTweetEl
 );
            console.log(firstTweetText);
 }
 }
})();
javascript loops web-scraping dom puppeteer
© www.soinside.com 2019 - 2024. All rights reserved.