在url上循环执行同样的操作

Looping over urls to do the same thing

本文关键字:操作 执行 url 循环      更新时间:2023-09-26

我正在搜寻一些站点。这是我的代码:

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();

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

但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的新手,所以我对这个愚蠢的问题感到抱歉。

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();
});

如果你不想要任何依赖项,那么定义你自己的递归函数也很容易(从这里开始):

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();