Node.js / Puppeteer - DOM NodeList для объекта JS - PullRequest
0 голосов
/ 21 октября 2018

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

H1 равен object.name и т. Д.

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

Это то, что мне нужно:

enter image description here

И это одна из моих попыток, но 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.log(n[0]);
    return n;
});

Ответы [ 2 ]

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

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

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

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

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

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

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

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

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

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

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

Цитирование непосредственно в документах Puppeteer

page.evaluate (pageFunction, ... args)

pageFunction Функция, которая будет оцениваться в контексте страницы

... args <... Serializable | JSHandle>Аргументы для передачи на 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.log(n[0]);
    return n;
}, selG);

Обратите внимание:

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

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

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

Подводя итог : функция, переданная в page.evaluate() CAN'T, использует переменные, объявленные oкроме этого, потому что он будет запущен в браузере, контекст, отделенный от вашего скрипта 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();
0 голосов
/ 21 октября 2018

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

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

Примечание: Обратите внимание, чтоЯ добавил selG в качестве отдельного аргумента после функции страницы.

page.evaluate(pageFunction, ...args)

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

...