2016-08-17 2 views
0

Первая часть:хранить несколько выскабливания данных в массиве

В настоящее время я скребу веб-страницу, чтобы получить ссылки, то я открываю каждые Царапины ссылки этой части работы отлично.

вторая часть:

проверить, если есть выбор поля (выбрать) параметры и хранится значение (ID) в массиве эта часть также работает отлично.

Третья часть:

Я хочу, чтобы цикл через них (выбор вариантов) и запустить событие щелчка и ждать ответа AJAX извлекает Infoproduct затем Stor его в массив.

У меня проблема в этой части. Я получил пустой массив, потому что return listProducts вызывается перед первым запуском this.eachThen.

function getInfosProduct(obj,variation) { 
    if (!variation) { 
     return [{ 
      name: getName(), 
      image: products.image.getElement.link + getImage(), 
      url: obj.url 
     }]; 
    } else { 
     return { 
      name: getName(), 
      image: products.image.getElement.link + getImage(), 
      url: variation.url, 
      idVariation: variation.id, 
      descVariation: variation.description 
     }; 
    } 
} 

function clickVariation(variation) { 
    if (variation.ok && variation.id != variation.ignore) { 
     chooseVariation(products.selector, variation.id); 
     return true; 
    } 
    return false; 
} 

casper.getInfosProducts = function(obj) { 
    if (obj.level == 0) { 
     return this.evaluate(getInfosProduct, obj,false); 
    } else { 
     listProducts = []; 
     this.eachThen(obj.levelVariation, function getInfosProducts(variation) { 
      isClick = this.evaluate(clickVariation, variation.data) 
      if (isClick) { 

       this.waitForSelectorTextChange('.selector', function() { 
        this.echo('The text on .selector has been changed.'); 
       }); 

       listProducts.push(this.evaluate(getInfosProduct, obj,variation.data)); 
           } 
     }); 
     return listProducts; 
    } 
}; 

Функция, чтобы вызвать событие изменения на выбора элемента

function chooseVariation(selector, valueToMatch) { 
    var select = document.querySelectorAll(selector), 
     found = false; 
    Array.prototype.forEach.call(select, function(opt, i) { 
     if (!found && opt.value.indexOf(valueToMatch) !== -1) { 
      select.selectedIndex = i; 
      found = true; 
     } 
    }); 
    // dispatch change event in case there is some kind of validation 
    var evt = document.createEvent("UIEvents"); // or "HTMLEvents" 
    evt.initUIEvent("change", true, true); 
    select[0].dispatchEvent(evt); 
} 

Это главный fucntion:

function startSraping(obj) { 
     casper.then(function switchAction() { 
      switch (obj.action) { 

       //......... some code ........ 

      // iterating through array links and open pages 
      case "openLinks": 
       this.each(links, function eachOpenLinks(self, link) { 
        if (link.ok) { 
         self.thenOpen(link.url, function thenOpenLinks() { 
          startSraping({ 
           url: link.url, 
           action: "getVariations" 
          }); 
         }); 
        } 
       }); 
       break; 

        // get all variations for each page opend 
       case "getVariations": 
        objVariations = this.getVariations(obj.url); 
        startSraping({ 
         url: obj.url, 
         action: "getInfosProducts", 
         objVariations: objVariations 
        }); 
        break; 

       case "getInfosProducts": 
        this.eachThen(obj.objVariations.list, function(levelVariation) { 
         infosProd = this.getInfosProducts({ 
          levelVariation: levelVariation.data, 
          url: obj.url, 
          level: obj.objVariations.level 
         }); 
         // Here I got an empty array 
         this.echo(JSON.stringify(infosProd), 'INFO'); 
        }); 
        break; 
      } 
     }); 
    } 
    casper.start(url, function start() { 
     startSraping({ 
      variation: variation, 
      action: "submitSearch" 
     }); 
    }); 
    casper.run(); 

ответ

1

Вы не можете вызвать асинхронную функцию (eachThen и waitForSelectorTextChange оба являются асинхронными) внутри функции, которая i должен возвращать результат от асинхронной функции синхронно (general reference). Поскольку CasperJS не поддерживает Promises, этот get немного сложный.

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

casper.getInfosProducts = function(obj, callback) { 
    if (obj.level == 0) { 
     this.then(function(){ 
      callback.call(this, arr.push(this.evaluate(getInfosProduct, obj,false)); 
     }); 
    } else { 
     var listProducts = []; 
     this.eachThen(obj.levelVariation, function getInfosProducts(variation) { 
      var isClick = this.evaluate(clickVariation, variation.data) 
      if (isClick) { 
       this.waitForSelectorTextChange('.selector', function() { 
        this.echo('The text on .selector has been changed.'); 
        listProducts.push(this.evaluate(getInfosProduct, obj, variation.data)); 
       }); 
      } 
     }); 
     this.then(function(){ 
      callback.call(this, listProducts); 
     }); 
    } 
}; 

В startSraping:

case "getInfosProducts": 
    this.eachThen(obj.objVariations.list, function(levelVariation) { 
     this.getInfosProducts({ 
      levelVariation: levelVariation.data, 
      url: obj.url, 
      level: obj.objVariations.level 
     }, function (infosProd){ 
      // this is the asynchronous callback 
      this.echo(JSON.stringify(infosProd), 'INFO'); 
     }); 
    }); 
    break; 
+0

гений ответ, "Я прочитал ваш пост о синхронной/асинхронной, то/ожидание, четкий и полный ответ :)". Я знал, почему он не работал, но не знал, как его решить. Но процесс останавливается, когда он достигает 'callback (listProducts)' – abdel

+0

Простите об этом. Я забыл правильно установить значение 'this' для обратного вызова –

+0

, он отлично работает, muchas gracias :) вы спасаете мою жизнь. Но я сделал 2 изменения: я исправил 'arr.splice', и я поместил' change.data' в переменную, потому что внутри 'wait' дата NULL вы знаете, почему. – abdel

Смежные вопросы