如何使用requestJS和cheerioJS刮取URL列表并在全局变量中存储数据?

时间:2016-07-21 00:01:18

标签: javascript for-loop asynchronous web-scraping requestjs

我有一个网址列表,其中有4个。对于每一个我想要抓取一些信息并将信息存储到名为allData的全局变量中。所以我的代码看起来像这样:

var request = require('request');
var cheerio = require('cheerio');

var urls = [url1,url2,url3,url4];
var allData = [];

for(var url in urls){
      request(url, function(err,response,body){
         var $ = cheerio.load(body);
         var data = $('h1.large','#title_main').text();
         allData.push(data);
   });
}

但是,由于使用请求的异步性,我意识到这不起作用。在最后一个循环中,“datas”中的所有数据都是相同的,来自url4。知道如何解决这个问题吗?真的需要这个功能。

1 个答案:

答案 0 :(得分:0)

很高兴您找到了适合您的解决方案。

你可能已经知道这已经过去了9个月,但是为了将来参考你也可以使用一些本地javascript数组函数,这些函数在每次迭代的范围内“关闭”(并避免为你的项目设置另一个依赖项) - 我在使用.forEach()的一些网络抓取工具中一直这样做:

urls.forEach(function(url){
    request(url, function(err,response,body){
        var $ = cheerio.load(body);
        var data = $('h1.large','#title_main').text();
        allData.push(data);
    });
})

Array.prototype中存在一些基于函数编程的方法,允许您在每次迭代(基本上冻结进入函数的参数)中执行数组中数据的函数。有一些函数如.forEach()允许您关闭其中包含异步代码的循环中的参数。

上面的代码导致四种方法异步执行。每个方法都传递给数组中的一个url。当每个请求完成时,allData将在request / cheerio解析的内容中附加结果。

如果您需要它们,您可以访问每个index函数迭代传递的forEach

urls.forEach(function(url,index){
    request(url, function(err,response,body){
        var $ = cheerio.load(body);
        var data = $('h1.large','#title_main').text();
        allData[index]=data;
    });
})