2014-04-02 41 views
0

有沒有辦法從指定的URL同步頁面源? 問題是,我有一長串url(如其中的1000個)來獲取和解析,並在回調中循環執行它非常痛苦,因爲它同時啓動所有fetchUrl函數,並根據代碼在回調中。node.js中的syncronous提取url?

Preferebly我想能夠:

  1. 獲取爲url1
  2. 解析爲url1源
  3. 保存結果分析結果到硬盤
  4. 獲取URL2
  5. 解析URL2源
  6. 將結果解析結果保存到hdd
  7. ..重複所有列表。

目前我使用包來獲取URL源解析cheerio

回答

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..'); 
}; 
+0

不錯!使用你的解決方案,就像一個魅力! – kaytrance

+0

這不會並行發出100個請求,它受到http客戶端的限制 - 只是想澄清一下。 –

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異步操作馬上走,而不是真正的序列化他們。

您還可以使用promise或node.js的多個異步管理庫中的任何一個。

+0

響應性這次不是問題。我知道我打破了設計模式,但爲了這個任務,我寧願同步做,至少在我的腦海裏,但似乎有一些適合我的情況的圖案,我不知道。 – kaytrance

+0

@查詢 - 那麼你可能使用了錯誤的工具。 – jfriend00

1

同步I/O和節點不要混合您的問題,一個基本方法。如果你確實想要做這個同步,你沒有通過使用節點獲得任何東西 - 它甚至不可能。你可以用Ruby代替。

其他答案是在生產服務器上執行此操作的正確方法。您應該將請求提交給某種可以限制併發性的隊列,因此您不會一次嘗試建立1000個連接。我喜歡batch

如果不生產,你可以使用節點的不穩定版本,你可以使用co它使用發電機通過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()); 
    } 
})(); 

運行帶:

node --harmony-generators random.js 

或者使用regenerator

regenerator -r random.js | node 
+0

不知道co,我會深深地看,謝謝。 – kaytrance