hellomello
hellomello

Reputation: 8585

Getting different results when using Puppeteer page.evaluate()

Why is it that my script will produce the correct results when doing this:

let data = await page.evaluate(async () => {

  let multipleVideosUnorderedList = await document
    .querySelector('article > div')
    .querySelector('ul');

  let video = [];

  if (multipleVideosUnorderedList != null) {

    let multipleVideosList = multipleVideosUnorderedList.children;
    console.log(multipleVideosList);

    for (i = 0; i < multipleVideosList.length; i++) {
      let rightBtn = document.querySelector(
        'button > div.coreSpriteRightChevron'
      );
      if (rightBtn) {
        await rightBtn.parentNode.click();
      }
      let videoUrl = multipleVideosList[i].querySelector('video');
      if (videoUrl) {
        video.push(videoUrl.getAttribute('src'));
      }
    }
  } else {
    video.push(document.querySelector('video').getAttribute('src'));
  }

  return {
    video
  };
});

console.log(data);

But when it deduce it down to just this:

let er = await page.evaluate(() => {

  let multipleVideosUnorderedList = document.querySelector('article > div').querySelector('ul');

  return {
    multipleVideosUnorderedList
  }
});

console.log(er);

the result is undefined. I know there's a lot more code in the former, but I just wanted to see it produce the correct element before I move on to grabbing everything else.

The idea was to take out the document.querySelector in code block and clean it up, to try to use page.$(selector) instead.

Upvotes: 1

Views: 182

Answers (1)

Vaviloff
Vaviloff

Reputation: 16838

Only serializable objects can go into and out of page.evaluate, a NodeList and a Node, which are found with querySelectorAll/querySelector, are not such things.

You probably would like to find an unordered list wich may contain several videos. If this is the case you could rewrite the code in the following way:

let outerVideos = await page.evaluate(() => {
  // convert the NodeList to an array
  let videos = [...document.querySelectorAll('article > div video')]
     // for each member of the array replace the video node with its src value
    .map(video => video.getAttribute('src')); 

  return videos;
});

console.log(outerVideos);

Upvotes: 1

Related Questions