Не определено при выборе кнопки в Puppeteer

#node.js #puppeteer

#node.js #puppeteer

Вопрос:

Почему я получаю undefined при запуске console.log(result); ?
Как я могу это исправить?

 const express = require('express');
const puppeteer = require('puppeteer');
const app = express();


(async () => {
  const browser = await puppeteer.launch({headless:false, devtools: true});
  const page = await browser.newPage();
  await page.goto('https://my.gumtree.com/login', {waitUntil: 'networkidle2'});
  await page.waitFor(4000);

// await page.waitForSelector('button[id="google-sign-in-button"]');
// await page.click('id[name="google-sign-in-button"]');


   const result = await page.evaluate(x => {
    return Promise.resolve(document.getElementById('google-sign-in-button'));
  }, 7);
  
console.log(result);
 

//await browser.close();
})();


app.listen(3000, function (){
    console.log('server started');
})
  

<button type="submit" id="google-sign-in-button" class="btn-icn-left btn-secondary btn-full-width btn-google-icon" data-social-login="type:googleplus,appId:67555700125-lvoarr4qau5lkhuks3bn3bl9u3bmmfuf.apps.googleusercontent.com" data-analytics="gaEvent:LoginAttempt,userData:{lip:Google}" data-q="google-sign-in-button">Sign in with Google</button>

введите описание изображения здесь

Ответ №1:

К сожалению, page.evaluate() может передавать только сериализуемые значения (грубо говоря, значения, которые может обрабатывать JSON). document.getElementById() возвращает элементы DOM, которые не являются сериализуемыми (они содержат методы и циклические ссылки). Несериализуемые данные обычно заменяются пустым объектом или undefined . Вам нужно либо вернуть сериализуемое значение, либо использовать что-то вроде page.$(selector) and ElementHandle API.

Комментарии:

1. Как я могу вернуть сериализуемый объект, чтобы я мог щелкнуть по нему?

2. К сожалению, вы не можете. Сериализуемые данные предназначены для… данные) Если вам нужен элемент для нажатия, используйте page.$(selector) и другие функции, которые возвращают ElementHandle . У ElementHandle есть .click() метод. Или вы можете щелкнуть внутри контекста браузера в page.evaluate() .

Ответ №2:

  • Нет необходимости переносить Promise.resolve возвращаемое значение из evaluate функции обратного вызова.
  • Попробуйте вернуть обычный объект или примитивное значение (сериализуемое) из evaluate .
 const result = await page.evaluate(x => {
  const el = document.getElementById('google-sign-in-button')
  const buttonContent = el.textContent
  return buttonContent
}, 7);
  

Чтобы нажать на кнопку, вам нужно использовать page.click метод вместо page.evaluate :

 await page.click("#google-sign-in-button");
  

Вы не можете работать с элементом DOM вне page.evaluate функции обратного вызова, потому что функция обратного вызова вызывается в контексте «браузера», а затем возвращаемое значение обрабатывается в Node.js код без каких-либо знаний о DOM вообще.

Комментарии:

1. и как мне нажать на кнопку?

2. Хорошо, но мне не нужно содержимое кнопки, мне нужна кнопка, чтобы я мог нажать на нее. Как я мог это сделать?

3. Чтобы нажать на кнопку, вам необходимо использовать page.click метод: await page.click("#google-sign-in-button'");

Ответ №3:

 (async () => {
  const browser = await puppeteer.launch({headless:false, devtools: true});
  const page = await browser.newPage();
  await page.goto('https://my.gumtree.com/login', {waitUntil: 'networkidle2'});
  await page.waitFor(4000);


//get the selector by its id
const myButton = await page.$('#google-sign-in-button');
myButton.click();


//await browser.close();
})();


app.listen(3000, function (){
    console.log('server started');
})