Puppeteer:如何获取节点列表的每个元素的内容?

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

我正在努力实现一些非常微不足道的事情:获取元素列表,然后使用每个元素的innerText做一些事情。

const tweets = await page.$$('.tweet');

据我所知,这会返回一个nodelist,就像浏览器中的document.querySelectorAll()方法一样。

我如何绕过它并得到我需要的东西?我试过各种各样的东西,比如:

[...tweets].forEach(tweet => {
  console.log(tweet.innerText)
});
javascript node.js google-chrome-devtools puppeteer headless-browser
2个回答
8
投票

page.$$():

你可以使用elementHandle.getProperty()jsHandle.jsonValue()的组合从innerText获得的ElementHandle获得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.$$(),并使用page.evaluate()

const tweets = await page.evaluate(() => Array.from(document.getElementsByClassName('tweet'), e => e.innerText));

tweets.forEach(tweet => {
  console.log(tweet);
});

5
投票

根据puppeteer docs here$$不返回节点列表,而是返回ElementHandle数组的Promise。它与NodeList不同。

有几种方法可以解决这个问题。

1. Using built-in function for loops called 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. Pass the elementHandle to the page.evaluate

无论你从await page.$$('.tweet')得到什么,都是一系列的elementHandle。如果你控制台,它会根据类型说JShandleElementHandle

忘记硬解释,更容易证明。

// 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) 
}

当然有多种方法可以解决这个问题,格兰特米勒在另一个答案中也回答了其中的几个问题。

© www.soinside.com 2019 - 2024. All rights reserved.