0

我有一个 URL 列表,比如说 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。知道如何解决这个问题吗?确实需要这个功能。

4

1 回答 1

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当每个请求完成时,将从请求/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;
    });
})
于 2017-04-28T20:27:45.970 回答