Как передать переменную, возвращенную из оценки, в другую оценку в Nightmare.js

В настоящее время я пытаюсь извлечь данные из таблицы с помощью Nightmare.js с помощью vo. Таблица, которую я пытаюсь извлечь, имеет несколько страниц, и мне нужно извлечь всю эту таблицу в строку externalHTML, которая позже будет преобразована в JSON. Код, который я использую, проходит через цикл, каждый из которых содержит функцию оценки(). Что я хочу сделать, так это иметь переменную, хранящую данные, которые я хочу извлечь (String), и добавлять к ней новые данные с каждым циклом. Однако я сталкиваюсь с проблемой, когда не могу отправить переменную из предыдущей оценки() в следующую. Вот функция запуска моего кода.

function *run() {
  var totalPageNumber = "";
  var nightmare = Nightmare({ show: true });
  yield nightmare
    .goto('https://www.svgame168.com/IGKiosk/guest/login.aspx')
    .select('#ctl00_ddlLanguage', 'th-TH')
    .wait(3000)
    .insert('input[name="ctl00$ContentPlaceHolder1$Login1$UserName"]', userName)
    .insert('input[name="ctl00$ContentPlaceHolder1$Login1$Password"]', password)
    .click('#ctl00_ContentPlaceHolder1_Login1_LoginButton')
    .wait(3000)
    .goto('https://www.svgame168.com/IGKiosk/playermgt/Default.aspx')
    .click('#ctl00_ContentPlaceHolder1_searchBtn')
    .wait(6000)
    .evaluate(function () {
      var result = "";
      var nextPageExist = document.evaluate("//a[contains(., '>')]", document, null, XPathResult.ANY_TYPE, null );
      nextPageExist = nextPageExist.iterateNext();result = document.querySelector("#ctl00_ContentPlaceHolder1_dataGridView").outerHTML;
      var totalPageNumber = document.querySelector("#main_content_table > tbody > tr > td > table:nth-child(5) > tbody > tr > td > table > tbody > tr > td > div:nth-child(4) > span > div:nth-child(1)");

      if (nextPageExist != null){
        nextPageExist.className += " nextPageExist1";
      }
      return totalPageNumber;
    })

  for (var i = 2; i <= 11; i++) {
    console.log("Currently on page " + i);
    yield nightmare
      .click(".nextPageExist" + (i - 1))
      .wait(6000)
      .evaluate(function (result) {
        var nextPageExist = document.evaluate("//a[text()='>']", document, null, XPathResult.ANY_TYPE, null );
        nextPageExist = nextPageExist.iterateNext();

        console.log(result);
        result += document.querySelector("#ctl00_ContentPlaceHolder1_dataGridView").outerHTML;
        //console.log(result);
        if (nextPageExist != null){
          var pageNumber = document.querySelector("#main_content_table > tbody > tr > td > table:nth-child(5) > tbody > tr > td > table > tbody > tr > td > div:nth-child(4) > span > div:nth-child(2) > span").innerHTML
          pageNumber = pageNumber.replace(/\D/g,'');
          nextPageExist.className += " nextPageExist" + pageNumber;
        }
        return result
      })
  }
  yield nightmare
    .end()
    .then(function (result) {
      console.log(tabletojson.convert(result));
    })
    .catch(function (error) {
      console.error('Search failed:', error);
    });
}

Я подозреваю, что мой синтаксис, когда я получаю переменную во второй оценке, неверен, но я не смог найти решение. Я пытался использовать это, и это все равно выдавало ошибку.

      .evaluate(function (result) {
        var nextPageExist = document.evaluate("//a[text()='>']", document, null, XPathResult.ANY_TYPE, null );
        nextPageExist = nextPageExist.iterateNext();

        console.log(result);
        result += document.querySelector("#ctl00_ContentPlaceHolder1_dataGridView").outerHTML;
        //console.log(result);
        if (nextPageExist != null){
          var pageNumber = document.querySelector("#main_content_table > tbody > tr > td > table:nth-child(5) > tbody > tr > td > table > tbody > tr > td > div:nth-child(4) > span > div:nth-child(2) > span").innerHTML
          pageNumber = pageNumber.replace(/\D/g,'');
          nextPageExist.className += " nextPageExist" + pageNumber;
        }
        return result
      }, result)

Приведенный выше код работает, если я удаляю переменную «результат» из каждой строки в оценке.


person Lucerna Sempiternus    schedule 30.01.2020    source источник


Ответы (1)


Ниже приведен способ вернуть результат из метода оценки и сохранить его, а также перейти на следующую страницу.

return nightmare
        .click(".nextPageExist" + (i - 1))
        .wait(5000) // wait till the page is loaded
        .evaluate(() => {
           //extract data from table
           //return the data
           return result
         })
        .then((result) => {
           //recieve the data from previous step 
           
           //add the result to an global array
           tableResults.push(result);

         })
     

приведенный выше код может выполнять итерацию внутри редуктора массива, как показано ниже, использование редуктора гораздо более рекомендуется, чем использование цикла for.

let pages = [1, 2, 3, 4] // assuming there are 4 pages, create an array with a 
                         //length of 4

pages.reduce(accumulator, currentValue, index, arr)
{
      accumulator.then(() => {
         return nightmare
        .click(".nextPageExist" + (currentValue - 1))
        .wait(5000) // wait till the page is loaded
        .evaluate(() => {
           //extract data from table
           //return the data
           return result
         })
        .then((result) => {
           //recieve the data from previous step 
           
           //add the result to an global array
           tableResults.push(result);

         })
      })
    

}, Promise.resolve());
person Faiz Mohammed    schedule 28.06.2020