【问题标题】:Looping over urls to do the same thing循环遍历 url 来做同样的事情
【发布时间】:2014-10-31 18:46:20
【问题描述】:

我正在尝试抓取一些网站。这是我的代码:

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

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

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

【问题讨论】:

  • 尝试在抓取之前添加console.log("Scraping " + urls.length + " pages."),并可能在您记录 URL 时将其括在引号中。列表中可能有空(或仅空格)输入。
  • 我的回答有帮助吗?有什么问题吗?如果它解决了你的问题,你可以accept 一个答案(只是让你知道)。

标签: javascript loops phantomjs screen-scraping


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 2019-06-16
    • 2014-12-29
    • 2018-07-07
    相关资源
    最近更新 更多