#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');
})