2015-04-20 3 views
0

Итак, я просматриваю страницу, собирая ссылки, затем я хотел бы просканировать эти ссылки, чтобы заполнить мой набор данных. Вот код:CasperJS evaluation() не выполняется изнутри каждого() блока

crawl.js:

var casper = require("casper").create({ 
    waitTimeout: 3000, 
    pageSettings: { 
     userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20130404 Firefox/23.0" 
    }, 
    clientScripts: ["includes/jquery.min.js"], 
    verbose: true 
}); 

var followers = require('./followers'); 
var currentPage = 1; 
var x = require('casper').selectXPath; 

Object.size = function(obj) { 
    var size = 0, key; 
    for (key in obj) { 
     if (obj.hasOwnProperty(key)) size++ 
    } 
    return size; 
}; 

var collectFollowers = function() { 
    var url; 
    this.echo("capturing page " + currentPage); 
    this.capture("wowhead-p" + currentPage + ".png"); 

    // don't go too far down the rabbit hole 
    if (currentPage >= 5 || !this.exists(x('//*[text()="Next ›"]'))) { 
     processFollowers.call(casper); 
     return terminate.call(casper); 
    } 

    currentPage++; 
    this.echo("requesting next page: " + currentPage); 
    url = this.getCurrentUrl(); 

    var links = this.evaluate(function() { 
     var obj = {} 
     $('.listview-cleartext').map(function(){ 
      obj[$(this).text()] = $(this).attr('href'); 
     }); 
     return obj; 
    }); 

    for (key in links) { 
     followers.followers[key] = links[key]; 
    } 

    this.echo("Page links: " + Object.size(followers.followers)); 
    //this.emit('update.followers', links); 
    this.thenClick(x('//*[text()="Next ›"]')).then(function() { 
     this.waitFor(function() { 
      return url !== this.getCurrentUrl(); 
     }, collectFollowers, processFollowers); 
    }); 
}; 

var processFollowers = function() { 
    this.echo("Total followers:" + Object.size(followers.followers)); 
    this.each(Object.keys(followers.followers), function(casper, key) { 
     this.thenOpen('http://wowhead.com' + followers.followers[key]).then(function() { 
      this.echo("On http://wowhead.com" + followers.followers[key]); 
      this.evaluate(function() { 
       this.echo("Inside the evaluate statement."); 
       if ($('a[href=#quests]').length) { 
        this.echo("Has quest!"); 
        $('a[href=#quests]').click(); 
        var questURL = $('#tab-quests').show().find('.listview-cleartext').attr('href'); 
        var questName = $('#tab-quests').show().find('.listview-cleartext').text(); 
        this.echo("Quest URL: " + questURL); 
        followers.followers[key] = {"name": key, "quest": {"url": questURL, "name": questName}}; 
       } else { 
        this.echo("Does not have quest!"); 
       }  
      }); 
     }); 
    }); 
} 

var terminate = function() { 
    this.echo("Done.").exit(); 
} 

casper.start("http://wowhead.com/followers=2"); 
casper.waitForSelector(x('//*[text()="Next ›"]'), collectFollowers, processFollowers); 
casper.run(); 

followers.js:

var require = patchRequire(require); 
var utils = require('utils'); 
var followers = {}; 
exports.followers = followers; 

последователей используется для хранения глобальной переменной, объект, который я постоянно создавать и обновлять, как я ползать страницы. Поэтому я просматриваю 3 страницы данных, собираю ссылки успешно и начинаю их обрабатывать. Как бы то ни было, CasperJS, похоже, успешно открывает каждую страницу, однако функция оценки никогда не вызывается.

Я получил эту функциональность, чтобы работать в PhantomJS с некоторой асинхронной логикой, но переключился на casper, потому что казалось, что это будет позаботиться под капотом. Я пробовал различные комбинации thenOpen(), then() и open(), thenOpen() без then() и т. Д. Что я испортил?

ответ

0

casper.evalute() - это изолированный контекст страницы таким же образом, как версия PhantomJS (page.evaluate()). Он не имеет доступа к переменным, определенным снаружи.

this внутри evaluate() относится к window и не casper и я сомневаюсь, что есть такая функция, как window.echo(). Если вы хотите получать сообщения консоли от контекста страницы, вам необходимо зарегистрироваться на remote.message событие:

casper.on("remote.message", function(msg){ 
    this.echo("remote: " + msg); 
}); 

Вы должны явно передать результат из контекста страницы и добавить его там:

var result = this.evaluate(function() { 
    console.log("Inside the evaluate statement."); 
    if ($('a[href=#quests]').length) { 
     console.log("Has quest!"); 
     $('a[href=#quests]').click(); 
     var questURL = $('#tab-quests').show().find('.listview-cleartext').attr('href'); 
     var questName = $('#tab-quests').show().find('.listview-cleartext').text(); 
     console.log("Quest URL: " + questURL); 
     return {"url": questURL, "name": questName}}; 
    } else { 
     console.log("Does not have quest!"); 
     return null; 
    } 
}); 
if (result) { 
    followers.followers[key] = {name: key, quest: result}; 
} 
+0

Спасибо, Артём. Это очень похоже на старую ревизию моего кода. У меня было подозрение, что я неправильно использовал пространства имен. Задача решена! –

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