Можно ли передавать информацию из браузера в область Node с помощью Nightmare.js (v2 Electron)?

Я использую Nightmare.js (v2.3.3) для автоматизации части моего рабочего процесса, когда мне нужно получить доступ к веб-сайту, который обновляет нашу базу данных. Мне удалось заставить Nightmare работать с основными вещами, такими как .type, .click и .screenshot, чтобы подтвердить, что я обращаюсь к этим страницам и ввожу информацию, которую намеревался.

Где я застрял, а документации, похоже, не хватает, так это в использовании .evaluate для извлечения информации со страницы. В документации это так:

.evaluate(fn [,arg1,arg2,...])

var selector = 'h1';
var text = yield nightmare
  .evaluate(function (selector) {
    // now we're executing inside the browser scope. 
    return document.querySelector(selector).innerText;
   }, selector); // <-- that's how you pass parameters from Node scope to browser scope 

Это все хорошо, но возможно ли пойти в обратном направлении и передать информацию из области браузера в область действия Node? Что я хотел бы сделать, так это вернуть все флажки на странице в виде массива, а затем прокрутить их в скрипте Nightmare.

Я также просмотрел множество вопросов GitHub и вопросов StackOverflow, чтобы найти ответ, и проблема, похоже, в том, что предыдущие версии были построены на PhantomJS, а v2+ использует Electron, поэтому трудно определить, какие ответы на самом деле все еще применимы к текущей версии. . Вот ответ, который показался мне понятным, но это было в 2014 году, поэтому я я думаю, что, скорее всего, это была версия PhantomJS. Для справки, это фрагмент, в котором, похоже, есть ответ о том, как перейти из браузера в область Node:

var p1=1,
    p2 = 2;

nightmare
  .evaluate( function(param1, param2){
        //now we're executing inside the browser scope.
        return param1 + param2;
     }, function(result){
        // now we're inside Node scope again
        console.log( result);
     }, p1, p2 // <-- that's how you pass parameters from Node scope to browser scope
  ) //end evaluate
  .run();

Но не кажется, что текущая версия Nightmare поддерживает этот формат .evaluate(fn, cb, arg1, arg2,...)?

Я просто хотел бы знать, возможно ли это, прежде чем я сойду с ума! Спасибо за любую помощь, пожалуйста, дайте мне знать, если вам нужна дополнительная информация, чтобы помочь ответить.


person ryanjwessel    schedule 19.05.2016    source источник
comment
Я не понимаю. В вашем первом фрагменте text должно содержаться значение, которое было передано из контекста страницы в контекст узла, не так ли? Имеет ли это?   -  person Artjom B.    schedule 19.05.2016
comment
@ArtjomB. не в моем понимании. yield nightmare просто запускает экземпляр кошмара, чтобы следовать цепочке инструкций.   -  person ryanjwessel    schedule 22.05.2016


Ответы (1)


Ты очень, очень близко. Одно из последних обновлений — использование Nightmare более перспективным способом. Это означает, что вам не нужно самостоятельно обрабатывать обратный вызов .evaluate(), результаты передаются по цепочке. Ваш второй пример, слегка измененный:

nightmare = require('nightmare')();
nightmare.goto('http://example.com');

var p1=1,
    p2=2;

nightmare
  .evaluate( function(param1, param2){
        return param1 + param2;
     }, p1, p2)
  .then(function(result){
    console.log(result); //prints 3
  });

Рекомендуется использовать .then(), но если вы действительно хотите использовать .run(), вы можете:

nightmare = require('nightmare')();
nightmare.goto('http://example.com');
var p1=1,
    p2=2;

nightmare
  .evaluate( function(param1, param2){
        return param1 + param2;
     }, p1, p2)
  .run(function(err, result){
    console.log(result);
  });
person Ross    schedule 20.05.2016
comment
Спасибо @Росс! На самом деле я просматривал вопросы GitHub и наткнулся на несколько ваших ответов, которые познакомили меня с .then и Promises. Совершенно новая концепция для меня, но я понимаю, почему Nightmare пошли в этом направлении. Таким образом, параметр, переданный .then, является возвращаемым значением предыдущей задачи в цепочке, в данном случае .evaluate? Кроме того, что такое .run? Я нигде не смог найти документацию по этому поводу, и разве это не лучшая практика для Nightmare? - person ryanjwessel; 22.05.2016
comment
Да, параметрами функции .then() будут результаты предыдущего действия. (Это немного упрощение, но здесь работает хорошо.) .run() не задокументировано, так как оно постепенно устаревает. Если вам интересно, обсуждение этого вопроса можно найти здесь. - person Ross; 22.05.2016
comment
Большое спасибо за помощь! Я неделю бился головой о стену, пытаясь разобраться в этом. Мне нужно будет еще немного прочитать промисы и .then, чтобы понять их полный потенциал. Я просто установил ваш ответ как принятый, надеюсь, это поможет другим, кто только начинает работать с Nightmare. - person ryanjwessel; 22.05.2016
comment
Рад помочь! Как бы там ни было, вы можете взглянуть на nightmare-examples, особенно пример с нативными промисами. - person Ross; 22.05.2016
comment
Спасибо еще раз! Это огромная помощь. Я чувствую, что это определенно должно быть связано с официальной документацией. - person ryanjwessel; 24.05.2016
comment
но не будет ли .then() своего рода end() текущим процессом? Каждый раз, когда я использую .then, я не могу связать другие методы с экземпляром кошмара. Что, если я хочу извлечь данные из середины моего скрипта автоматизации? - person ProblemsOfSumit; 10.05.2017