有没有办法从指定的网址同步获取网页来源? 问题是我有很长的url列表(比如1000个)来获取和解析,并且在回调中循环执行它是非常痛苦的,因为它同时启动所有fetchUrl函数,并根据代码解析它在回调中。
我希望能够:
目前我使用 fetch 包来获取网址来源和 cheerio 进行解析。
答案 0 :(得分:2)
使用async.queue
,request
,cheerio
这是使用async.queue
var Concurrency = 100; // how many urls to process at parallel
var mainQ =async.queue(function(url,callback){
request(url,function(err,res,body){
// do something with cheerio.
// save to disk..
console.log('%s - completed!',url);
callback(); // end task
});
},Concurrency);
mainQ.push(/* big array of 1000 urls */);
mainQ.drain=function(){
console.log('Finished processing..');
};
答案 1 :(得分:1)
节点的体系结构和作为Web服务器的响应性取决于它不进行同步(例如阻塞)网络操作。如果您要在node.js中开发,我建议您学习如何管理异步操作。
这是运行序列化异步操作的设计模式:
function processURLs(arrayOfURLs) {
var i = 0;
function next() {
if (i < arrayOfURLs.length) {
yourAsyncOperation(arrayOfURLS[i], function(result) {
// this callback code runs when async operation is done
// process result here
// increment progress counter
++i;
// do the next one
next();
});
}
}
next();
}
为了获得更好的端到端性能,您实际上可能希望立即执行N个异步操作,而不是真正将它们全部序列化。
您还可以对node.js使用promises或任何一个异步管理库。
答案 2 :(得分:1)
同步I / O和节点不混合。如果真的想要进行同步,那么使用Node就无法获得任何东西 - 它甚至都不可能。你可以改用Ruby。
其他答案是在生产服务器上执行此操作的正确方法。您应该将请求提交到某种队列,这可能会限制并发性,因此您不会尝试同时建立1000个连接。我喜欢batch。
如果这不是用于生产并且您可以使用不稳定版本的Node,则可以使用co获取同步样式语法,该语法使用生成器通过{{停止在函数中间执行1}}关键字:
yield
使用以下命令运行:
var co = require('co'),
request = require('co-request'),
cheerio = require('cheerio');
var urls = [];
for (var i = 0; i < 10; i++)
urls.push('http://en.wikipedia.org/wiki/Special:Random');
co(function * () {
for (var i = 0; i < urls.length; i++) {
var res = yield request(urls[i]);
console.log(cheerio.load(res.body)('#firstHeading').text());
}
})();
或使用regenerator:
node --harmony-generators random.js