Puppeteer:如何获取节点列表中每个元素的内容?
Puppeteer: How to get the contents of each element of a nodelist?
我正在尝试实现一些非常琐碎的事情:获取元素列表,然后对每个元素的 innerText
做一些事情。
const tweets = await page.$$('.tweet');
据我所知,这个 returns 一个节点列表,就像浏览器中的 document.querySelectorAll()
方法一样。
我如何遍历它并获得我需要的东西?我尝试了各种东西,例如:
[...tweets].forEach(tweet => {
console.log(tweet.innerText)
});
page.$$():
您可以使用 elementHandle.getProperty()
and jsHandle.jsonValue()
to obtain the innerText
from an ElementHandle
obtained with page.$$()
:
的组合
const tweets = await page.$$('.tweet');
for (let i = 0; i < tweets.length; i++) {
const tweet = await (await tweets[i].getProperty('innerText')).jsonValue();
console.log(tweet);
}
如果您准备使用 forEach()
方法,您可以将循环包装在一个 promise 中:
const tweets = await page.$$('.tweet');
await new Promise((resolve, reject) => {
tweets.forEach(async (tweet, i) => {
tweet = await (await tweet.getProperty('innerText')).jsonValue();
console.log(tweet);
if (i === tweets.length - 1) {
resolve();
}
});
});
page.evaluate():
或者,您可以使用 page.$$()
entirely, and use page.evaluate()
:
跳过
const tweets = await page.evaluate(() => Array.from(document.getElementsByClassName('tweet'), e => e.innerText));
tweets.forEach(tweet => {
console.log(tweet);
});
根据 puppeteer 文档 here, $$
Does not return a nodelist, instead it returns a Promise of Array of ElementHandle。它与 NodeList 有很大不同。
有几种方法可以解决这个问题。
1。使用内置函数进行循环 page.$$eval
此方法在页面内运行 Array.from(document.querySelectorAll(selector))
并将其作为第一个参数传递给 pageFunction
。
所以获取 innerText 如下所示,
// Find all .tweet, and return innerText for each element, in a array.
const tweets = await page.$$eval('.tweet', element => element.innerText);
2。将 elementHandle
传递给 page.evaluate
从await page.$$('.tweet')
得到的都是elementHandle数组。如果你控制台,它会根据类型说 JShandle
或 ElementHandle
。
忘了硬解释,演示更容易。
// let's just call them tweetHandle
const tweetHandles = await page.$$('.tweet');
// loop thru all handles
for(const tweethandle of tweetHandles){
// pass the single handle below
const singleTweet = await page.evaluate(el => el.innerText, tweethandle)
// do whatever you want with the data
console.log(singleTweet)
}
当然有多种方法可以解决这个问题,格兰特·米勒在另一个答案中也回答了其中的一些。
我正在尝试实现一些非常琐碎的事情:获取元素列表,然后对每个元素的 innerText
做一些事情。
const tweets = await page.$$('.tweet');
据我所知,这个 returns 一个节点列表,就像浏览器中的 document.querySelectorAll()
方法一样。
我如何遍历它并获得我需要的东西?我尝试了各种东西,例如:
[...tweets].forEach(tweet => {
console.log(tweet.innerText)
});
page.$$():
您可以使用 elementHandle.getProperty()
and jsHandle.jsonValue()
to obtain the innerText
from an ElementHandle
obtained with page.$$()
:
const tweets = await page.$$('.tweet');
for (let i = 0; i < tweets.length; i++) {
const tweet = await (await tweets[i].getProperty('innerText')).jsonValue();
console.log(tweet);
}
如果您准备使用 forEach()
方法,您可以将循环包装在一个 promise 中:
const tweets = await page.$$('.tweet');
await new Promise((resolve, reject) => {
tweets.forEach(async (tweet, i) => {
tweet = await (await tweet.getProperty('innerText')).jsonValue();
console.log(tweet);
if (i === tweets.length - 1) {
resolve();
}
});
});
page.evaluate():
或者,您可以使用 page.$$()
entirely, and use page.evaluate()
:
const tweets = await page.evaluate(() => Array.from(document.getElementsByClassName('tweet'), e => e.innerText));
tweets.forEach(tweet => {
console.log(tweet);
});
根据 puppeteer 文档 here, $$
Does not return a nodelist, instead it returns a Promise of Array of ElementHandle。它与 NodeList 有很大不同。
有几种方法可以解决这个问题。
1。使用内置函数进行循环 page.$$eval
此方法在页面内运行 Array.from(document.querySelectorAll(selector))
并将其作为第一个参数传递给 pageFunction
。
所以获取 innerText 如下所示,
// Find all .tweet, and return innerText for each element, in a array.
const tweets = await page.$$eval('.tweet', element => element.innerText);
2。将 elementHandle
传递给 page.evaluate
从await page.$$('.tweet')
得到的都是elementHandle数组。如果你控制台,它会根据类型说 JShandle
或 ElementHandle
。
忘了硬解释,演示更容易。
// let's just call them tweetHandle
const tweetHandles = await page.$$('.tweet');
// loop thru all handles
for(const tweethandle of tweetHandles){
// pass the single handle below
const singleTweet = await page.evaluate(el => el.innerText, tweethandle)
// do whatever you want with the data
console.log(singleTweet)
}
当然有多种方法可以解决这个问题,格兰特·米勒在另一个答案中也回答了其中的一些。