node.js中的同步提取网址?

时间:2014-04-02 06:44:19

标签: node.js

有没有办法从指定的网址同步获取网页来源? 问题是我有很长的url列表(比如1000个)来获取和解析,并且在回调中循环执行它是非常痛苦的,因为它同时启动所有fetchUrl函数,并根据代码解析它在回调中。

我希望能够:

  1. 获取url1
  2. 解析url1源
  3. 将结果解析结果保存到hdd
  4. 获取url2
  5. 解析url2源
  6. 将结果解析结果保存到hdd
  7. ..重复所有列表。
  8. 目前我使用 fetch 包来获取网址来源和 cheerio 进行解析。

3 个答案:

答案 0 :(得分:2)

使用async.queuerequestcheerio这是使用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