Кукловод: Как получить содержимое каждого элемента нодлиста? - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь достичь чего-то очень тривиального: получить список элементов, а затем сделать что-то с innerText каждого элемента.

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

Из того, что я могу сказать, это возвращаетсписок узлов, как и метод document.querySelectorAll() в браузере.

Как мне просто зациклить его и получить то, что мне нужно?Я пробовал разные вещи, такие как:

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

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Согласно документам кукловода здесь , $$ Не возвращает список узлов, вместо этого он возвращает обещание массива 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) 
}

Конечно, есть несколько способовЧтобы решить эту проблему, Грант Миллер также ответил на некоторые из них в другом ответе.

0 голосов
/ 16 октября 2018

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() метод, вы можете заключить цикл в обещание:

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);
});
...