2012-09-15 6 views
0

페이지를 파싱하고 관련 링크를 추출하는 데 사용되는 CasperJS를 사용하여 스파이더를 작성하려고합니다. 문제의 사이트는 파일 및 폴더의 계층 적보기를 제공합니다. 필자는 파일 구조를 통한 네비게이션을 수행하는 재귀 적 메소드를 작성했지만, 함수의 첫 번째 반복 후에는 함수가 올바르게 실행 중이더라도 배열이 null을 반환합니다. 문제를 확인하는 데 도움이 될 것입니다 정말 감사하겠습니다. matchesWhitelist가 false 인 경우 매핑 기능이 아무것도 반환하지 않기 때문에재귀 적 메서드에서 배열을 null로 설정 중

var processPage = function() { 

    //Gather links 
    var links = this.evaluate(function() { //links is the array being set to null 
     var elements = document.querySelectorAll("a"); 
     return Array.prototype.map.call(elements, function(e) { 
      //check link matches our white list 
      var matchesWhitelist = false; 

      var fileDescription = e.querySelector("span").innerHTML; 
      console.log("span text:" + fileDescription); 

      //begin checking 
      if (fileDescription.indexOf('.mp3') != -1) matchesWhitelist = true; 
      //if (fileDescription.indexOf('.wmv') != -1) .... etc 

      //failing that is the link for a folder rather than a file 
      var hrefLink = e.getAttribute("href"); 
      if (hrefLink.indexOf('folder-files') != -1) matchesWhitelist = true; 

      if (matchesWhitelist) { 
       console.log('match'); 
       console.log('Adding link: ' + hrefLink) 
       return hrefLink; 
      } 
      else { 
       console.log('no match'); 
      } 
     }); 
    }); 

console.log("linkslength: " + links.length); // links will be null upon recursion 

for (var i = 0; i < links.length; i++) { 

     //check link matches our 'whitelist' 
     this.thenOpen("https://TLD" + links[i]).then(function() { 
      this.echo("New URL: " + this.getCurrentUrl()); 

      //check for files 
      if (this.exists(".fileDownload")) { 
       //extract link 
      } else { 
       //assume that this is a 'folder' link and send to be processed for more links 
       casper.then(processPage); //continue recursion 
      }; 
     }); 
    } 

감사

+0

"링크는"null이 될 것입니다. Array.map은 항상 배열을 반환합니다. – Bergi

+0

첫 번째 반복에서 console.log ("linkslength :"+ links.length)는 (예상대로) "linkslength : 8"을 반환합니다. 두 번째 반복에서는 같은 줄이 출력됩니다. TypeError : 'undefined'가 객체가 아닙니다 ('links.length'평가). console.log에 링크를 전달하면 null이 출력됩니다. – SteveOLeary

+0

또한 두 번째 반복에서 Array.map 인라인 함수는 '일치'및 '링크 추가'콘솔 출력을 얻고 있으므로 제대로 실행됩니다. 그것은 매우 이상합니다. 일단 인라인 함수가 링크를 빠져 나가면 갑자기 범위를 벗어나는 것과 같습니다. – SteveOLeary

답변

2

감소한 세트가 필요한 것 같습니다.

즉, .map 대신 .filter을 사용해야하며 링크를 유지하려면 truey 값을, 그렇지 않으면 false 값을 반환해야합니다.

return Array.prototype.filter.call(elements, function(e) { 

    //... 

    if (matchesWhitelist) { 
     console.log('match'); 
     console.log('Adding link: ' + hrefLink) 
     return true; 
    } 
    else { 
     console.log('no match'); 
    } 
}); 

로깅이 필요하지 않은 경우 matchesWhitelist을 반환합니다.

return Array.prototype.filter.call(elements, function(e) { 

    //... 

    return matchesWhitelist; 
}); 

로깅을 없애고 필터를 줄일 수 있습니다.

return Array.prototype.filter.call(elements, function(e) { 

    return e.getAttribute("href").indexOf('folder-files') != -1 || 
      e.querySelector("span").innerHTML.indexOf('.mp3') != -1; 
}); 
+0

그러나 이것은 요소를 URL로 매핑하지 않습니다. – Bergi

0

links 배열의 일부 항목은, undefined 있습니다.

기타 문제 : 페이지의 모든 링크가 범위를 포함해야하는 것은 아닙니다. innerHTML에 액세스하면 기능이 중단됩니다. 그리고 : 이미 크롤링 된 페이지가 표시되지 않습니다. 모든 순환 링크는 크롤러를 무한 루프로 안내합니다.

0

나는 둘 다 나에게 문제의 원인에 점점 도움이되었다 나는, 당신의 답변을 모두 받아 들일 수 있으면 좋겠다. 필자는 필 요한 부분 만 지나치게 복잡하게 만들고 있었고 필자는 필 요한 요소만으로 집합을 줄이기 위해 먼저 필터를 적용한 다음 매핑을 수행하여 필요한 링크가있는 배열을 반환 할 수 있도록하여이 문제를 해결했습니다. 내가 사용 결국 코드는 스크립트가 지금 작동하고 그리고 난이 필요로하는 모든 링크를 추출

var processPage = function() { 
    var url; 
    //Gather links 
    var links = this.evaluate(function() { 
     var elements = document.querySelectorAll("a"); 
     var filteredElementsList = Array.prototype.filter.call(elements, function(e) { 

      //check link matches our white list 

      var matchesWhitelist = false; 

      var fileDescription = e.querySelector("span").innerHTML; 
      console.log("span text:" + fileDescription); 

      //begin checking 
      if (fileDescription.indexOf('.mp3') != -1) matchesWhitelist = true; 

      //failing that is the link for a folder rather than a file 
      var hrefLink = e.getAttribute("href"); 
      if (hrefLink.indexOf('folder-files') != -1) matchesWhitelist = true; 

      if (matchesWhitelist) { 
       console.log('match'); 
       console.log('Adding link: ' + hrefLink) 
      } else { 
       console.log('no match'); 
      } 

      return matchesWhitelist; 
     }); 

     return Array.prototype.map.call(filteredElementsList, function(e) { 
      return e.getAttribute("href"); 
     }); 
    }); 

했다. 도움에 다시 한번 감사드립니다.