我希望它如何运作:
首先,我使用 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);
}
}
})();