CasperJS цикл или итерации через несколько веб-страниц?

У меня есть CasperJS script, который сбрасывает рейтинги и даты с одной веб-страницы. Теперь я хочу очистить одни и те же данные с нескольких страниц под одним и тем же веб-сайтом. Как я могу прокручивать разные подстраницы с учетом этого кода:

var ratings = [];
var dates = [];
var casper = require('casper').create({

    pageSettings: {
        loadImages:  false,         
        loadPlugins: false          
    },
    logLevel: "debug",             
    verbose: true                   
});

var fs = require('fs');

function getRatings() {
    var ratings = document.querySelectorAll('#BVRRRatingOverall_Review_Display > div.BVRRRatingNormalImage > img');
    return Array.prototype.map.call(ratings, function(e) {
        return e.getAttribute('title');
    });
}

function getDate() {
    var dates = document.querySelectorAll('#BVSubmissionPopupContainer > div.BVRRReviewDisplayStyle5Header > div.BVRRReviewDateContainer > span.BVRRValue.BVRRReviewDate');

    return Array.prototype.map.call(dates, function(e) {

        return e.innerHTML;

    });
}

casper.start('http://www.t-mobile.com/cell-phones/samsung-galaxy-s-5.html?bvrrp=9060/reviews/product/1/598aea53-16d0-4c12-b53a-105157092c52.htm', function(){

    this.echo('hi');
});

casper.then(function() {

    ratings = this.evaluate(getRatings);
    dates = this.evaluate(getDate);

    this.echo(ratings);
});


casper.run(function() {

    this.echo(ratings.length + ' ratings found:');

     for(var i=0; i<ratings.length; i++){
        ratings[i] = ratings[i]+': '+dates[i];
        dates[i] = '';
     }
    this.echo(ratings);
    var content = ratings;

    content = content.join("\n");

    fs.write("C:/Users/Karan/Copy/tweesis/implementation/scraping/samsungratings.txt", content, 'w'); 

    this.echo(dates.length + ' dates found:').exit();



});

Любая помощь приветствуется:)

Ответы

Ответ 1

Поскольку существует кнопка следующей страницы, вы можете использовать ее для рекурсивного перемещения всех страниц:

function getRatingsAndWrite(){
    ratings = casper.evaluate(getRatings);
    dates = casper.evaluate(getDate);

    casper.echo(ratings);
    casper.echo(ratings.length + ' ratings found:');

    for(var i=0; i<ratings.length; i++){
        ratings[i] = ratings[i]+': '+dates[i];
        dates[i] = '';
    }
    casper.echo(ratings);
    var content = ratings;

    content = content.join("\n");

    fs.write("C:/Users/Karan/Copy/tweesis/implementation/scraping/samsungratings.txt", content, 'a'); 

    casper.echo(dates.length + ' dates found:');

    var nextLink = ".BVRRPageLink.BVRRNextPage > a";
    if (casper.visible(nextLink)) {
        casper.thenClick(nextLink);
        casper.then(getRatingsAndWrite);
    } else {
        casper.echo("END")
    }
}

casper.start('http://www.t-mobile.com/cell-phones/samsung-galaxy-s-5.html?bvrrp=9060/reviews/product/1/598aea53-16d0-4c12-b53a-105157092c52.htm');

casper.then(getRatingsAndWrite);

casper.run();

Связанный ответ A: CasperJS разборки следующей страницы после нажатия кнопки.

Ответ 2

Этот код может помочь вам: вы определяете в массиве объектов нужные URL-адреса, селектора для каждой страницы и в цикле вы делаете то, что хотите сделать с этими свойствами.

Вы можете использовать метод click в цикле вместо URL-адреса.

var navigation = [
    {
        url: 'http://www.t-mobile.com/cell-phones/samsung-galaxy-s-5.html?bvrrp=9060/reviews/product/1/598aea53-16d0-4c12-b53a-105157092c52.htm', 
        selectorRatings:'#BVRRRatingOverall_Review_Display > div.BVRRRatingNormalImage > img', selectorDate :'#BVSubmissionPopupContainer > div.BVRRReviewDisplayStyle5Header > div.BVRRReviewDateContainer > span.BVRRValue.BVRRReviewDate'
    }
    ,{
        url: 'yourSecondUrl, etc...',
        selectorRatings:'#BVRRRatingOverall_Review_Display > div.BVRRRatingNormalImage > img',
        selectorDate :'#BVSubmissionPopupContainer > div.BVRRReviewDisplayStyle5Header > div.BVRRReviewDateContainer > span.BVRRValue.BVRRReviewDate'
    }
],
content = "";

    casper.start()
    .then(function(){
        //loop on the array
        navigation.forEach(function(navIndex){
            //open url : property url 
            casper.thenOpen(navIndex.url)
            //wait for the page to load -> must be useless because thenOpen() do it
            .waitForUrl(navIndex.url, function(){
                //get the value of attribute title of adequate selector
                var ratings = this.getElementAttribute(navIndex.selectorRatings, 'title'),
                //get the HTML of adequate selector
                var dates = this.getHTML(navIndex.selectorDates);
                this.echo(ratings);
                this.echo(dates);
                content = content +  ' ' + ratings + ' ' + dates;
            }); 
        });
    })
    .run(function() {
            this.echo('----------- All steps done ------------\n');
            this.exit();
    });

Ответ 3

Спасибо Fanch и Artjom B. Оба ваших ответа оказали рабочее решение. Я использовал рекурсивную прогулку по "следующим" страницам на странице, заданной Artjom B. Далее я добавил функцию wait(), чтобы убедиться, что перед тем, как очистить их, была загружена следующая страница рейтингов. Без этой функции wait() мы очищаем одну и ту же страницу несколько раз между моментом, когда нажата "следующая", и соответственно. следующая страница делается погрузка. См. Рабочий код ниже:

var ratings = [];
var dates = [];
var casper = require('casper').create({

    pageSettings: {
        loadImages:  false,         
        loadPlugins: false          
    },
    logLevel: "debug",               
    verbose: true                   
});

var fs = require('fs');

function getRatings() {
    var ratings = document.querySelectorAll('#BVRRRatingOverall_Review_Display > div.BVRRRatingNormalImage > img');
    return Array.prototype.map.call(ratings, function(e) {
        return e.getAttribute('title');
    });
}

function getDate() {
    var dates = document.querySelectorAll('#BVSubmissionPopupContainer > div.BVRRReviewDisplayStyle5Header > div.BVRRReviewDateContainer > span.BVRRValue.BVRRReviewDate');

    return Array.prototype.map.call(dates, function(e) {

        return e.innerHTML;

    });
}

function getRatingsAndWrite(){
    ratings = casper.evaluate(getRatings);
    dates = casper.evaluate(getDate);


    casper.echo(ratings.length + ' ratings found:');

     for(var i=0; i<ratings.length; i++){
        var rating = ratings[i].substr(0,1);
        ratings[i] = rating +': '+dates[i];
        dates[i] = '';
    } 

    var content = ratings;

    content = content.join("\n");

    fs.write("<filepath to write content>", content, 'a'); 

    casper.echo(dates.length + ' dates found:');

    var nextLink = ".BVRRPageLink.BVRRNextPage > a";
    if (casper.visible(nextLink)) {
        casper.thenClick(nextLink);
        casper.wait(3000);
        casper.then(getRatingsAndWrite);
    } else {
        casper.echo("END")
    }
}

casper.start('http://www.t-mobile.com/cell-phones/htc-one-m8.html');

casper.then(getRatingsAndWrite);

casper.run();