我有一个网址列表,其中有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。知道如何解决这个问题吗?真的需要这个功能。
答案 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;
});
})