2017-09-22 12 views
0

필자는 페이지를 긁는 데 아주 오랜 시간이 걸린다는 점을 제외하면 매우 잘 작동하는 CasperJS 스크립트를 작성했습니다. 간단히 말해서 수천 개의 페이지를 스크랩하는 CasperJS 스크립트를 더 빨리 실행하는 모범 사례

, 여기에 의사 코드입니다 : 요소를
  • casper.start() 탐색을 시작하고 로그인하는
  • casper.then()에서 나는 루프를 통해 배열을 스크랩 및 저장

    1. 내 기능 내
    2. casper.thenOpen() 각 링크를 열고 내 기능을 스크랩하도록 호출하십시오.

    많은 링크를 폐기하는 데 완벽하게 (그리고 충분히 빠름) 작동합니다. 하지만 수천의 경우 (지금은 100K 링크 어레이로 스크립트를 실행하고 있습니다), 실행 시간은 무한합니다. 첫 번째 10K 링크는 3h54m10s에서, 다음 10K는 2h18m27s에서 스크랩되었습니다.

    2 개의 10K 배치의 차이를 약간 설명 할 수 있습니다. 첫 번째는 루프 배열 &의 100K 링크 저장 공간을 포함합니다. 이 시점부터 스크립트는 페이지를 열어 스크랩합니다. 그러나 배열이 대략 30 분 후에 갈 준비가되었음을 알았으므로 정확히 시간 차이를 설명하지 못합니다.

    각 루프가 빌드되어 어레이에 저장된 후 스크랩이 발생하기를 바라는 for 루프에 casper.thenOpen()을 삽입했습니다. 지금, 나는 이것이 실패 했음에도 불구하고 성능 측면에서 어떤 것도 바꿀 것인가?

    그 점은 제가 지금 염두에 두어야 할 유일한 단서입니다. 스크립트 실행의 실행 시간을 크게 줄이려면 누구나 기꺼이 최선의 방법을 공유하고 싶다면 매우 감사 할 것입니다. . 아마 답변보다 더 많은 질문을 가지고 있지만의 시도하자이 시점에서

    var casper = require('casper').create(); 
    var fs = require('fs'); 
    
    // This array maintains a list of links to each HOL profile 
    
    // Example of a valid URL: https://myurl.com/list/74832 
    var root = 'https://myurl.com/list/'; 
    var end = 0; 
    var limit = 100000; 
    var scrapedRows = []; 
    
    // Returns the selector element property if the selector exists but otherwise returns defaultValue 
    
    function querySelectorGet(selector, property, defaultValue) { 
        var item = document.querySelector(selector); 
        item = item ? item[property] : defaultValue; 
        return item; 
    } 
    
    // Scrapping function 
    function scrapDetails(querySelectorGet) { 
    
        var info1 = querySelectorGet("div.classA h1", 'innerHTML', 'N/A').trim() 
        var info2 = querySelectorGet("a.classB span", 'innerHTML', 'N/A').trim() 
        var info3 = querySelectorGet("a.classC span", 'innerHTML', 'N/A').trim() 
    
        //For scrapping different texts of the same kind (i.e: comments from users) 
        var commentsTags = document.querySelectorAll('div.classComments'); 
        var comments = Array.prototype.map.call(commentsTags, function(e) { 
        return e.innerText; 
        }) 
    
    // Return all the rest of the information as a JSON string 
        return { 
        info1: info1, 
        info2: info2, 
        info3: info3, 
    
        // There is no fixed number of comments & answers so we join them with a semicolon 
        comments : comments.join(' ; ') 
        }; 
    } 
    
    casper.start('http://myurl.com/login', function() { 
    this.sendKeys('#username', 'username', {keepFocus: true}); 
    this.sendKeys('#password', 'password', {keepFocus: true}); 
    this.sendKeys('#password', casper.page.event.key.Enter, {keepFocus: true}); 
    
        // Logged In 
        this.wait(3000,function(){ 
    
        //Verify connexion by printing welcome page's title 
        this.echo('Opened main site titled: ' + this.getTitle()); 
        }); 
    }); 
    
    casper.then(function() { 
    
        //Quick summary 
        this.echo('# of links : ' + limit); 
        this.echo('scraping links ...') 
    
        for (var i = 0; i < limit; i++) { 
    
        // Building the urls to visit 
        var link = root + end; 
    
         // Visiting pages... 
         casper.thenOpen(link).then(function() { 
          // We pass the querySelectorGet method to use it within the webpage context 
          var row = this.evaluate(scrapDetails, querySelectorGet); 
          scrapedRows.push(row); 
    
          // Stats display 
          this.echo('Scraped row ' + scrapedRows.length + ' of ' + limit); 
         }); 
    
        end++; 
        } 
    
    }); 
    
    casper.then(function() { 
        fs.write('infos.json', JSON.stringify(scrapedRows), 'w') 
    }); 
    
    casper.run(function() { 
        casper.exit(); 
    }); 
    
  • 답변

    0

    :

    편집 # 1

    은 여기 아래에있는 내 코드입니다.

    예를 들어 Curl이 아닌 CasperJS를 사용하는 특별한 이유가 있습니까? Javascript를 사용하는 사이트를 긁어 모으는 경우 CasperJS의 필요성을 이해할 수 있습니다. 또는 스크린 샷을 찍고 싶습니다. 그렇지 않으면 Curl을 PHP 나 Python과 같은 스크립팅 언어와 함께 사용하고 내장 된 DOM 구문 분석 함수를 활용할 것입니다. 물론 Scrapy와 같은 전용 스크래핑 도구를 사용할 수 있습니다. 사용할 수있는 도구가 많이 있습니다.

    다음 '명백한'질문 : 배열이 정말로 필요합니까 그 큰? 당신이 달성하고자하는 것은 명확하지 않다. 추출한 링크를 데이터베이스에 저장할 것을 원한다. 작은 배치로 프로세스를 분할하는 것이 가능하지 않습니까?지속적으로 성능 문제가 발생할 수밖에 없다 배열을 크기 조정 var theArray = new Array(1000);

    : 고정 크기 배열 예를 선언함으로써 충분한 메모리를 할당에 도움이

    한 가지입니다. 새 항목이 배열에 추가 될 때마다 값 비싼 메모리 할당 작업이 백그라운드에서 수행되어야하며 루프가 실행될 때 반복됩니다.

    코드를 표시하지 않으므로 의미있는 개선점을 제안 할 수 없으므로 일반 성은 권장 할 수 없습니다.

    +0

    답장을 보내 주셔서 감사합니다 @ 익명! PhantomJS, CasperJS 및 SlimmerJS가 웹 스크래핑에 가장 많이 사용되는 언어라는 것을 알고 있었기 때문에 Curl을 고려하지 않았습니다. 당신의 답을 바탕으로, 컬이 트릭을 할 것 같아요. 그래서 나는 확실히 그 장면을 보여줄 것입니다. 내가 import.io를 사용하여 근근이 살아가고 있지만, 나는 자신의 계획을 감당할 수 없어서 CasperJS에 자신을 가르치기로 결심했다. 수십만 개의 웹 페이지를 다 써야 할 필요가 있기 때문에 URL을 저장하기 위해 커다란 배열이 필요합니다. 나는 여기에 다시 메모리를 할당하지 않았고, 이것 역시 시도해보고 결과를 비교할 것입니다. 내 코드를 내 질문으로 업데이트했습니다.) – DFATPUNK