循环网址做同样的事情

时间:2014-10-31 18:46:21

标签: javascript loops phantomjs screen-scraping

我想要抓几个网站。这是我的代码:

for (var i = 0; i < urls.length; i++) {
    url = urls[i];
    console.log("Start scraping: " + url);

    page.open(url, function () {
        waitFor(function() {
            return page.evaluate(function() {
                return document.getElementById("progressWrapper").childNodes.length == 1;
            });

        }, function() {
            var price = page.evaluate(function() {
                // do something
                return price;
            });

            console.log(price);
            result = url + " ; " + price;
            output = output + "\r\n" + result;
        });
    });

}
fs.write('test.txt', output);
phantom.exit();

我想抓取数组网址中的所有网站,提取一些信息,然后将此信息写入文本文件。

但是for循环似乎有问题。在不使用循环的情况下仅抓取一个站点时,所有站点都可以正常工作。但是对于循环,首先没有任何反应,然后是行

console.log("Start scraping: " + url);
显示

,但有一次太多了。 如果url = {a,b,c},那么phantomjs会:

Start scraping: a 
Start scraping: b 
Start scraping: c 
Start scraping:

似乎没有调用page.open。 我是JS的新手,所以我很抱歉这个愚蠢的问题。

1 个答案:

答案 0 :(得分:4)

PhantomJS是异步的。通过使用循环多次调用page.open(),您基本上会急于执行回调。在完成新请求之前,您将覆盖当前请求,然后再次覆盖该请求。你需要一个接一个地执行它们,例如:

page.open(url, function () {
    waitFor(function() {
       // something
    }, function() {
        page.open(url, function () {
            waitFor(function() {
               // something
            }, function() {
                // and so on
            });
        });
    });
});

但这很乏味。有些实用程序可以帮助您编写更好的代码,如async.js。您可以通过npm将其安装在phantomjs脚本的目录中。

var async = require("async"); // install async through npm
var tests = urls.map(function(url){
    return function(callback){
        page.open(url, function () {
            waitFor(function() {
               // something
            }, function() {
                callback();
            });
        });
    };
});
async.series(tests, function finish(){
    fs.write('test.txt', output);
    phantom.exit();
});

如果您不想要任何依赖项,那么定义您自己的递归函数也很容易(来自here):

var urls = [/*....*/];

function handle_page(url){
    page.open(url, function(){
        waitFor(function() {
           // something
        }, function() {
            next_page();
        });
    });
}

function next_page(){
    var url = urls.shift();
    if(!urls){
        phantom.exit(0);
    }
    handle_page(url);
}

next_page();
相关问题