Nightmare Js не возвращает NodeList
Здравствуйте. Я использую Nightmare JS в Node Js проекте. Вопрос по этому коду:
async function someFunc() { let nightmare; try { nightmare = Nightmare({show: true, typeInterval: 10, waitTimeout: 5000}); await nightmare .goto(`https://example.com`) .click(".button") .wait(".someClass") let result = await nightmare.evaluate(function () { return document.querySelectorAll(".someClass"); }); console.log(result); } catch (error) { throw error; } finally { await nightmare.end(); } } "someClass" содержит несколько элементов(например,3). Я хочу получить в result NodeList, но я получаю только пустой объект. Этот код работает, только если я сразу возвращаю текстовое значение, например так: return document.querySelectorAll(".someClass")[0].textContent; Почему я не могу вернуть NodeList в result ? |
Знаете, я уж отвечал на этот вопрос - так сказать, "в практическом смысле", - потом удалил свой ответ (раз он спрашивающему не интересен, то чего им маячить?)
Но теперь я ещё раз на него отвечу - на этот раз "по существу". Зачем? -- А потому что мне обидно, что единственный нормальный русскоязычный форум про Node.js выглядит умирающим. Итак, ответ по существу. Когда-то давно умные люди придумали специальное устройство ("девайс") для общения в сети Энторнеты, оно называется "браузер". Это устройство умеет делать только три вещи - изготовлять из html-строки "документ-объектную модель" (DOM), разукрашивать её (DOM) всякими цветами и размерами (CSS) и динамически - если надо - её изменять (JavaScript) в рамках полученного "документа". Больше это тупое устройство - "браузер" - ничего делать не умеет. Обратим внимание на его последнее (в списке) умение. Что делает в браузере код на языке JavaScript типа такого? document.querySelectorAll(".someClass"); Поскольку тупой браузер - при помощи своего первого умения - уже построил из "документа" (т.е., фактически, из банальной строки, полученной в виде октет-стрима по интернетам) "документ-объектную модель", то данный код имеет возможность обратиться к этой самой DOM и выбрать из неё (из объекта - выбрать подобъекты) кусочки, удовлетворяющие условиям выборки. И если мы в консоле браузера напишем магические букавы: console.log(document.querySelectorAll(".someClass");) то тупой браузер нам тут же, в консоль, и напишет искомую NodeList, т.е. "СПИСОК УЗЛОВ DOM (document-object-model)". Проблемка заключается в том, что NodeList ("список узлов DOM") существует только в браузере. А что делает крутой модуль Nightmare? (я его попробовал - он, и вправду, крутой) 1. Делает запрос по указанному URL и получает в ответ html-строку в виде октет-стрима. 2. Вызывает браузер Chromium (как он есть "ядро" десктопного приложения Электрон) и просит создать из полученного "документа(строки)" DOM. 3. На языке JavaScript обращается к созданной DOM с запросом коллекции document.querySelectorAll(".someClass");и получает ответ в виде "кусочков подобъектов, собранных из объекта"... в виде чего?... 4. Поскольку Nightmare - это не тупой браузер, то она получает результат своего запроса - в виде той самой СТРОКИ, которую браузер когда-то получил и интерпретировал как "Документ-Объектную-Модель". Nightmare - это не браузер, она не умеет оперировать "узлами DOM" (теми самыми, которыми браузер так услужливо изображает нам у себя в консоли в ответ на наш запрос). В качестве ответа она умеет понять только "строку". Ну всё, я устал. Если кто не согласен с ответом - милости прошу разъяснить детали. А если не последует разъяснений - ну и хуй с ним, с форумом. |
|
Да вообще, это вопрос про "типы данных". В javascript он же никогда не стоит, как в "правильных" языках, но это он - в таком вот, несколько неожиданном виде.
Мы же не удивимся, если попытаться открыть в каком-нибудь приложении файл, тип которого это приложение не поддерживает (ну там, открыть html-документ в Фотошопе), и он там не откроется. Здесь примерно тот же случай. "Узлы DOM" и их коллекции (NodeList) - это, вроде бы, объекты, но специфические - браузерные объекты, тип которых Nightmare (да видимо, Нода вообще) не понимает. И функция, которая передаётся в аргумент метода evaluate, должна вернуть какой-нибудь понятный ей тип данных - строку или массив строк, или объект с ключами и значениями-строками. Вот, собсна, и всё. |
сам автор nightmarejs уже сказал, что это все устарело и он больше не разрабатывает этот проект
|
Да это не важно. Express тоже "устарел", и его никто больше не разрабатывает. А его знаменитый аффтар сказал, что Нода - это отстой, и он теперь пишет на Go.
И как дальше жить? |
я думаю: пока жив web на javascript'е, nodejs не умрет тоже ) ну или как go будет манипулировать dom'ом ) без js? Ну максимум mvc, и приплыли )
https://stackoverflow.com/q/29886552 By default, {} objects are not iterable, but why? Would the disadvantages outweigh the potential benefits of objects being iterable? What are the issues associated with this? In addition, because {} objects are different from "Array-like" collections and "iterable objects" such as NodeList, HtmlCollection, and arguments, they can't be converted into Arrays. https://github.com/segmentio/nightmare/issues/617 -- отсюда, наверное, вывод: надо парсить nodeList в evalute, а не возвращать в node и парсить там )... или возвращать document.body.innerHTML в нод, в нод создавать инстанс дом'а, и его парсить... а что будет если вернуть document.querySelector(".someClass") (не querySelectorAll)... )) |
Это всё равно, document.querySelector(".someClass") вернёт один непонятный "узел". Можно так -
return document.querySelector(".someClass").parentElement.innerHTML А внутри этой функции можно делать что угодно, только возвращать понятные результаты - elem.id или elem.innerHTML, или elem.textContent, elem.href, elem.src - или массивы этого всего собирать. Но - внутри этой функции, она как раз для этого и предназначена. Всё, что в её теле пишется, это клиенткий javascript в браузере, любой. |
это должно быть понятно, что в evalute и надо все парсить...
|
Часовой пояс GMT +3, время: 03:44. |