所以我试图在 Twitter 上抓取一个页面来获取推文:
我想要获取元素;文本、图像、视频分开,但我不断得到一个空数组
//Scraper.js
const puppeteer = require('puppeteer');
const fs = require('fs');
async function scrapeTwitter() {
try {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://twitter.com/coindesk');
await page.waitForLoadState('networkidle2');
const html = await page.content();
const $ = cheerio.load(html);
const tweets = $('[data-testid="tweet"]');
const posts = [];
tweets.each(function () {
const text = $(this).find('.tweet-text').text().trim();
const image = $(this).find('.tweet-image').attr('src');
const video = $(this).find('.tweet-video').attr('src');
posts.push({ text, image, video });
});
await browser.close();
return posts;
} catch (error) {
console.error('Error scraping Twitter:', error);
return [];
}
}
module.exports = scrapeTwitter;
我不会将 Cheerio 与 Puppeteer 一起使用。 Puppeteer 已经可以使用实时页面,因此将整个内容序列化以转储到静态 HTML 解析器中是没有意义的。如果您想抓取更多推文,则需要向下滚动,然后重新快照整个页面,以使 Cheerio 与动态站点保持同步。
除此之外,您的选择器不会为我返回任何内容。也许尝试这样的事情:
const puppeteer = require("puppeteer"); // ^22.6.0
const url = "<Your URL>";
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.goto(url, {waitUntil: "domcontentloaded"});
const tweetSel = '[data-testid="tweet"]';
await page.waitForSelector(tweetSel);
const data = [];
for (let i = 0; i < 50 && data.length < 20; i++) {
const preLen = await page.$$eval(
tweetSel,
els => els.length
);
await page.keyboard.press("PageDown");
try {
await page.waitForFunction(
`document.querySelectorAll('${tweetSel}').length > ${preLen}`,
{timeout: 2_000}
);
} catch (err) {
// ...
}
const chunk = await page.$$eval(tweetSel, els =>
els.map(el => ({
text: el
.querySelector('[data-testid="tweetText"]')
.textContent.trim(),
photo: el
.querySelector('[data-testid="tweetPhoto"] img')
?.getAttribute("src"),
}))
);
for (const e of chunk) {
if (data.every(f => f.text !== e.text)) {
data.push(e);
}
}
}
console.log(data);
console.log(data.length);
})()
.catch(err => console.error(err))
.finally(() => browser?.close());