Node.js / Puppeteer - DOM NodeList в объект JS

Я хочу преобразовать NodeList в объект.

H1 - это object.name и так далее.

Я до сих пор не могу понять точное поведение page.evaluate().

Вот что мне нужно:

Node.js / Puppeteer - DOM NodeList в объект JS

И это одна из моих попыток, но gp всегда не определен:

await page.waitForNavigation();

const selG = 'body > div.content-home > div > div.box > div > div:nth- child(2) > div.col-md-12.no-padding > div:nth-child(4) > div:nth-child(2) > div.col-xs-12';
await page.waitForSelector(selG);
const g = await page.evaluate( (selG) => {
    let gp = document.querySelector(selG); //null
    let n = Array.from(gp.querySelectorAll('h1'), element => element.textContent);
    console.info(n[0]);
    return n;
});
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 186
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы должны передать переменную selG в page.evaluate(), используя следующий метод:

const g = await page.evaluate(selG => { /* ... */ }, selG);

Note: Notice the that I added selG as a separate argument after the page function.

page.evaluate(pageFunction, ...args)

Это должно помешать document.querySelector(selG) вернуть null.

Ответ принят как подходящий

page.evaluate() запускает функцию, которую вы передаете, непосредственно в браузер и у него нет размаха (доступ к переменным) сценария NodeJS, запустившего Puppetter.

Чтобы полностью понять, попробуйте следующее:

1 - скопируйте свою функцию как есть

2 - превращает его в самозапускающуюся функцию ([your-function])(), результат следующий (я добавил еще одну строку console.info(selG);)

((selG) => {
  console.info(selG); // I added this line
  let gp = document.querySelector(selG);
  let n = Array.from(gp.querySelectorAll('h1'), element => element.textContent);
  console.info(n[0]);
  return n;
})()

3 - вставьте прямо в консоль devtools

Поступая таким образом, вы выполняете более менее (с точки зрения понимания) то, что делает page.evaluate(), то есть запускает функцию, которую вы передаете непосредственно в браузер. Что в результате? Это Cannot read property 'querySelectorAll' of null, потому что, как вы отметили, gp имеет значение null.

Но сконцентрируйтесь на console.info(selG);, который я добавил ... он записывает undefined ... это большая проблема!

Почему это происходит?

Взгляните на саму функцию, переменная selG не существует, поэтому let gp = document.querySelector(selG); не может ничего вернуть. selG определен в сценарии, который вы использовали для запуска Puppeteer, но функция, которую вы передаете page.evaluate(), будет запускаться в браузере, а не в контексте выполнения узла.

Цитирование прямо из документов Puppeteer

page.evaluate(pageFunction, ...args)

pageFunction Function to be evaluated in the page context

...args <...Serializable|JSHandle> Arguments to pass to pageFunction

используйте (как сказал Грант) второй остаток args, чтобы передать переменную selG вашей функции.

Следуя исходному коду с небольшими изменениями

await page.waitForNavigation();

const selG = 'body > div.content-home > div > div.box > div > div:nth- child(2) > div.col-md-12.no-padding > div:nth-child(4) > div:nth-child(2) > div.col-xs-12';
await page.waitForSelector(selG);
const g = await page.evaluate( (SELECTOR) => {
    let gp = document.querySelector(SELECTOR);
    let n = Array.from(gp.querySelectorAll('h1'), element => element.textContent);
    console.info(n[0]);
    return n;
}, selG);

Пожалуйста, обрати внимание:

  • что я передаю переменную selG (последняя строка) в pageFunction (ваша функция)

  • pageFunction получает переменную и сохраняет ее в переменной SELECTOR

  • pageFunction, чем потребляет полученный SELECTOR

Обобщить: функция, переданная в page.evaluate(), CAN'T потребляет переменные, объявленные вне нее, потому что она будет запущена в браузере, в контексте, отделенном от вашего скрипта NodeJS (написанного для запуска самого Puppeteer).

Попробуйте мой код, он должен работать без изменений. Дайте мне знать, если это достаточно ясно.

БОНУС

Помните, что если вы хотите использовать данные, относящиеся к DOM, у вас есть как минимум три разных метода, которые делают то же самое.

Ниже вы найдете мой пример, в котором я хочу прочитать атрибут href первой ссылки, которую я нахожу на странице. В первом примере, как и в вашем случае, используется page.evaluate(), в последних двух примерах показан другой подход с использованием некоторых других API-интерфейсов Puppeteer.

const SELECTOR = '[href]:not([href = ""])';
let link;

// compare the three following examples, they all do the same
link = await page.evaluate((sel) => 
    document.querySelector(sel).getAttribute('href')
, SELECTOR);
link = await page.$eval(SELECTOR, el => el.getAttribute('href'));
link = await page.$(SELECTOR).getProperty('href').jsonValue();

не могли бы вы помочь мне? он снова стал неопределенным после того, как я добавил свой класс. Мне нужно создать массив объектов jsfiddle.net/keypdamf

nanquim 25.10.2018 22:50

@tramada предоставьте мне репозиторий GitHub, и я посмотрю на него

NoriSte 28.10.2018 17:50

Другие вопросы по теме