사이트를 통째로 다운로드

통째로 다운로드하면 뭐가 좋음?

  • 사이트가 다운되거나, 인터넷에 연결되지 않은 상태에서도 사이트를 볼 수 있다.
  • 로컬에 HTML을 다운로드 해두면 수비게 검색을 수행할 수 있다.
  • 사이트 전체를 Database에 저장해 놓고 여러가지 분석을 수행해 볼 수 있다.

링크 따라다니며 다운로드하기

통째로 다운로드 하려면, 톱 페이지의 링크 정보를 바탕으로 HTML을 순회하며 한 페이지씩 내려받아야 한다.

프로그램을 만들어보자

3단계까지 링크 타고 들어가서 HTML 파일을 다운로드 파는 프로그램을 만들어보자

//0203_01_getall.js
// 모듈 로드
var client = require('cheerio-httpcli');
var request = require('request');
var fs = require('fs');
var urlType = require('url');
var path = require('path');

//-----공통 설정---
//링크 탐색 단계 지정
var LINK_LEVEL = 3;

//기준 URL 페이지
var TARGET_URL = "https://nodejs.org/api/";
var list ={};

console.log('start');

// 메인 처리
downloadRec(TARGET_URL, 0);

//지정 URL을 최대 level단계까지 다운로드
function downloadRec(url, level){

    //최대 Level 확인
    if(level >= LINK_LEVEL) return ;

    //이미 다운받은 사이트는 무시
    if(list[url]) return;
    list[url] = true;

        //외부 페이지는 무시
    var us = TARGET_URL.split("/");
    us.pop();
    var base = us.join("/");
    console.log(base);
    if (url.indexOf(base) < 0) return;

    //HTML을 취득
    client.fetch(url, {}, function(err, $, res ){

        //링크된 페이지를 획득
        $("a").each(function(idx){

            //<a> 태그의 링크를 획득
            var href = $(this).attr('href');
            if(!href) return;

            // 상대 경로를 절대 경로로 변환
            href = urlType.resolve(url, href);

            // '#' 이후를 무시(a.html#aa와 a.html#bb는 같다)
            href = href.replace(/\$.+$/,""); //말미의 #을 제거
            downloadRec(href, level +1);
        });

        //페이지 저장(파일명 지정)    
        if(url.substr(url.length-1,1)=='/'){
            url += "index.html"; //인덱스 자동 추가
        }    

        var savepath = url.split("/").slice(2).join("/");
        checkSaveDir(savepath);
        console.log(savepath);
        fs.writeFileSync(savepath, $.html());        
    });
}

//저장할 디렉토리 존재 유무 확인
function checkSaveDir(fname){
    //디렉토리 부분만 검출
    var dir = path.dirname(fname);

    //디렉토리를 재귀적으로 생성
    var dirlist = dir.split("/");
    var p = "";
    for (var i in dirlist){
        p += dirlist[i] + "/";
        if(!fs.existsSync(p)){
            fs.mkdirSync(p);
        }
    }
}

Node.js의 동기 함수와 비동기 함수

Node.js의 네트워크나 파일 처리 등의 함수는 비동기로 구현되어 있다.

비동기 함수를 호출하면 함수의 처리가 완료된 시점에서 콜백 함수가 호출된다

// 비동기 함수 mkdir

var fs = require('fs');

console.log("mkdir 실행");
fs.mkdir("test", function(){
    console.log("폴더 생성 완료");
});
console.log("mkdir 실행 완료. 결과 대기");

동기 함수

// 동기 함수
var fs = require('fs');

//디렉토리를 동기적으로 생성
console.log("mkdir 실행");
if(!fs.existsSync("test3")){
    fs.mkdirSync("test3");
    console.log("test3 생성완료");
}else{
    console.log("test3이 이미 있으므로 생성 안 함");
|
console.log("mkdir 완료");

results matching ""

    No results matching ""