2014-04-02 5 views
0

지정된 URL에서 자동으로 페이지 소스를 가져 오는 방법이 있습니까? 문제는 내가 가져오고 파싱 할 수있는 URL이 길다는 것입니다 (예 : 1000 개). 콜백의 루프에서 처리하는 것은 매우 어렵습니다. 왜냐하면 동시에 모든 fetchUrl 함수를 시작하고 그에 따라 구문을 분석하기 때문입니다. 콜백 코드.node.js의 Syncronous 가져 오기 URL?

Preferebly 나는 수 있도록하고 싶습니다 : 얻기

  1. URL1
  2. 결과를 분석
  3. 저장 결과는
  4. 은 URL2
  5. 구문 분석 URL2 소스
  6. 을 얻기 HDD하는 구문 분석 URL1 소스 결과를 파싱 결과를 hdd로 저장
  7. .. 모든 목록에서 반복하십시오.

은 현재 내가 이 URL 소스와 구문 분석 안녕를 얻을 수 패키지를 가져 오기 사용합니다.

답변

2

는 함께 사용하지 마십시오 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

노드의 아키텍처와 웹 서버로서의 응답 성은 동기식 (예 : 차단) 네트워크 작업을 수행하지 않는 것에 달려 있습니다. node.js에서 개발할 것이라면 비동기 작업을 관리하는 방법을 배우는 것이 좋습니다. 당신이 실제로 N 비동기 작업이 가자 한 번이 아니라 진정으로 그들 모두를 직렬화 할 수 있습니다, 더 나은 엔드 - 투 - 엔드 성능을

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(); 
} 

:

여기 직렬화 비동기 작업을 실행하기위한 디자인 패턴입니다.

node.js에 대한 약속 또는 여러 비동기 관리 라이브러리를 사용할 수도 있습니다. 여기 async.queue, request, cheerio를 사용

+0

이번에는 응답성에 문제가 없습니다. 나는 디자인 패턴을 깨고 있다는 것을 알고 있지만,이 작업을 위해 필자는 적어도 내 마음 속에서는 동 기적으로 할 것이지만, 내가 알지 못하는 나의 경우에 적합한 파 테론이있는 것으로 보인다. – kaytrance

+0

@ 퀘스트 - 아마도 당신은 틀린 도구를 사용하고있을 것입니다. – jfriend00

1

동기화 I/O와 노드를 사용하여 문제에 대한 기본적인 접근 방법이다. 이 실제로이 동기화를 원한다면 노드를 사용하여 아무 것도 얻지 못합니다. 실제로는 불가능합니다. 대신 Ruby를 사용할 수 있습니다.

다른 답변은 프로덕션 서버에서이 작업을 수행하는 올바른 방법입니다. 동시성을 제한 할 수있는 일종의 대기열에 요청을 제출하여 한꺼번에 1000 개의 연결을 시도하지 않아야합니다. 나는 이것에 대해 batch을 좋아한다.

이 생산하지 않고 당신이 노드의 불안정한 버전을 사용할 수 있다면, 당신은 yield 키워드를 통해 함수의 중간에 실행을 중지하는 발전기를 사용 co를 사용하여 동기화 스타일의 구문 얻을 수 있습니다 :

regenerator

node --harmony-generators random.js 

또는 사용 :

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 -r random.js | node 
+0

공동에 대해 알지 못했을 때, 나는 안으로 깊이 들여다 볼 것입니다, 감사합니다. – kaytrance