자바스크립트로 웹 크롤링 하는 방법

안녕하세요. 오늘은 자바스크립트로 크롤링 하는 법을 알아보려고 해요. 먼저 많은 분들이 궁금해하시는 웹 스크래핑과의 차이를 설명드릴게요. 이 둘은 서로 관련되어 있지만, 각각 다른 목적과 과정을 가지고 있는 개념이라고 이해하시면 되는데요.

 

크롤링과 웹 스크래핑의 차이

크롤링이란 인터넷상의 웹 페이지들을 방문하고 정보를 수집하는 과정이에요. 크롤러(또는 스파이더)라 불리는 프로그램이 웹 페이지를 방문하고, 그 페이지에 있는 링크들을 따라가며 다른 페이지로 이동하면서 정보를 수집해요.

 

웹 스크래핑은 그 수집한 정보를 추출하고 원하는 형태로 가공하는 과정까지 포함한 개념입니다. 웹 스크래핑은 웹 크롤링을 기반으로 하지만, 더 많은 데이터 처리 작업이 포함되어 있어요.

 

간단한 예를 들어볼게요. 웹 크롤링을 통해 온라인 쇼핑몰의 상품 페이지들을 방문하고, 각 페이지의 상품 정보를 수집할 수 있어요. 그리고 웹 스크래핑을 사용하여 수집한 상품 정보들 중에서 필요한 부분만 추출하고, 원하는 형식으로 가공하여 텍스트 파일이나 데이터베이스에 저장하는 작업을 진행할 수 있죠.

 

주의사항

크롤링을 하기 전에 주의할 사항이 있습니다. 대상 웹사이트의 'robots.txt' 파일을 꼭 확인해 보세요. 이 파일은 웹 사이트가 크롤러에게 어떤 페이지를 수집할 수 있는지, 어떤 페이지는 금지되어 있는지에 대한 정보를 담고 있습니다.

/*
 *파일위치: 도메인주소/robots.txt (예: naver.com/robots.txt)
 *아래와 같은 형식으로 되어있음
 */
 
User-agent: * 	  //모든 크롤러에 적용
Disallow: /new    //new경로로 시작하는 페이지들은 허용안함
Disallow: /*      //모든페이지 허용안함
Allow: /wiki      //wiki경로로 시작하는 페이지들은 허용

 

또한 너무 빈번한 요청으로 웹 사이트의 서버에 부하를 주지 않도록 주의하세요. 요청 간격을 적절하게 조절해서 서버에 문제를 일으키지 않도록 해야 합니다. 대규모 웹사이트의 경우, 크롤링 요청에 제한을 두기도 하니 이 점도 참고해 주세요.

사전준비

자 이제 시작하겠습니다. 브라우저의 콘솔 창에서 실행하기 위해 이번에도 CORS 우회 프록시 서버를 이용할 거예요. 처음이신 분들은 아랫글을 참고해 주세요. 뭘 설치하거나 환경설정을 하는 건 아니고, 웹사이트에 들어가서 활성화만 해주면 끝이에요.

 

자바스크립트로 웹스크래핑 하는 방법

 

자바스크립트로 웹스크래핑 하는 방법

안녕하세요. 오늘은 자바스크립트(JavaScript)로 웹 스크래핑(Web Scraping) 하는 방법에 대해 알아볼 거예요. 웹 스크래핑이란 웹 페이지에 있는 정보를 추출하는 과정이에요. 웹페이지는 HTML로 작성

toyou101.tistory.com

 

그리고 사용하시는 브라우저에서 F12 키를 눌러 개발자 도구를 열고, 콘솔 탭을 선택합니다. 웹 스크래핑 할 때와 마찬가지로 요청 헤더 정보인 User-Agent를 추가해야 해요. 혹시 추가하는 이유가 궁금하신 분들은 아랫글을 참고해 주세요.

 

자바스크립트 웹스크래핑으로 구글 검색 결과 가져오기

 

자바스크립트 웹스크래핑으로 구글 검색 결과 가져오기

안녕하세요. 이번 시간에는 사용하고 계신 인터넷 브라우저 콘솔에서 웹스크래핑 할 수 있는 자바스크립트를 만들 거예요. 웹스크래핑 대상은 구글의 검색 결과입니다! 입력받은 키워드로 검색

toyou101.tistory.com

 

크롤링 코드 작성

자바스크립트 코드는 웹 스크래핑 할 때와 크게 다르지 않아요. fetch를 사용해 웹 서버로부터 데이터를 요청하고 응답을 받습니다. 먼저 fetch가 잘 되는지 확인을 위해 링크는 따라 들어가지 않고 지정한 페이지에 대해서만 데이터를 수집하도록 할게요.

 

테스트는 위키백과 홈페이지로 하겠습니다. '/wiki' 경로로 시작하는 페이지들은 크롤러를 허용하고 있기 때문이에요!

//cors 우회 프록시 서버 URL
const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
// 수집 대상 URL
const url = 'https://ko.wikipedia.org/wiki/%ED%8F%AC%ED%84%B8:%EC%9A%94%EC%A6%98_%ED%99%94%EC%A0%9C';
// 크롤링 함수
async function crawl(url) {
    // 수집중인 URL
    const decodedUrl = decodeURI(url);
    console.log(`크롤링 ${decodedUrl} ...`);
    // URL에서 데이터를 가져옴
    const response = await fetch(proxyUrl + url, {
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7'
        }
    });
    // 응답 데이터를 문자열로 변환
    const htmlString = await response.text();
    // HTML 문자열을 파싱하여 DOM 객체 생성
    const parser = new DOMParser();
    const htmlDOM = parser.parseFromString(htmlString, 'text/html');
    // 데이터 추출
    const title = htmlDOM.querySelector('title').textContent;
    // 페이지내의 텍스트만 가져오기
    const content = htmlDOM.querySelector('#mw-content-text').textContent;
    // 추출한 데이터에서 연속된 개행 문자를 하나의 공백으로 대체    
    const contentWithSingleNewlines = content.replace(/\n{2,}/g, '\n');
    console.log(`Title: ${title}\nContent: ${contentWithSingleNewlines}\n`);
}
// 실행
crawl(url)
    .then(() => {
        console.log('데이터 수집 완료');
    })
    .catch(err => console.error(err));

 

실행 화면 ▼

크롤링실행1

 

해당 페이지 내 모든 텍스트를 수집한 결과입니다! 가져온 데이터를 분석하고 가공하면 유의미한 정보를 얻을 수 있는 거죠. 이번에는 해당 페이지의 링크들을 따라가며 그 페이지들까지 데이터를 수집해 볼게요.

 

재귀 호출을 사용하여 링크를 따라 들어가도록 합니다. 그리고 링크가 깊으면 시간이 너무 오래 걸리니 깊이를 지정해서 첫 번째 링크만 들어가도록 할게요.

//cors 우회 프록시 서버 URL
const proxyUrl = 'https://cors-anywhere.herokuapp.com/';
// 수집 대상 URL
const url = 'https://ko.wikipedia.org/wiki/%ED%8F%AC%ED%84%B8:%EC%9A%94%EC%A6%98_%ED%99%94%EC%A0%9C';
// 링크 깊이
const depth = 1;
// 딜레이 시간 
const delayTime = 100;
// 수집한 데이터를 저장할 배열
const data = [];
// 크롤링 함수
async function crawl(url, depth) {
    // 수집중인 URL
    const decodedUrl = decodeURI(url);
    console.log(`수집중 ${decodedUrl} ...`);
    // URL에서 데이터를 가져옴
    const response = await fetch(proxyUrl + url, {
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
            'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7'
        }
    });

    // 응답 데이터를 문자열로 변환
    const htmlString = await response.text();
    // HTML 문자열을 파싱하여 DOM 객체 생성
    const parser = new DOMParser();
    const htmlDOM = parser.parseFromString(htmlString, 'text/html');
    try {
        // 데이터 추출
        const title = htmlDOM.querySelector('title').textContent;
        const content = htmlDOM.querySelector('#mw-content-text').textContent;
        // 추출한 데이터를 배열에 저장
        data.push({
            title,
            content
        });
    } catch (e) {
        console.log(e);
        return;
    }
    // 링크 깊이가 0이면 함수 종료
    if (depth === 0) {
        return;
    }
    // 링크 추출
    const links = htmlDOM.querySelectorAll('a');
    for (const link of links) {
        // href 속성이 없으면 건너뜀
        if (!link.hasAttribute('href')) {
            continue;
        }
        // href 속성값 추출
        const href = link.getAttribute('href');
        // 동일 도메인에 있는 URL만 수집
        if (href.startsWith('https://ko.wikipedia.org') || href.startsWith('/wiki')) {
            // 링크 추출 후 딜레이 시간만큼 대기한 후 재귀적으로 호출
            await new Promise(resolve => setTimeout(resolve, delayTime));
            const nextUrl = new URL(href, url).href;
            // 링크 깊이가 0 이상인 경우에만 수집
            if (depth > 0) {
                await crawl(nextUrl, depth - 1);
            }
        }
    }
}
// 실행
crawl(url, depth).then(() => {
    console.log('크롤링 완료');
    console.log(JSON.stringify(data, null, 2));
}).catch(err => console.error(err));

 

실행 화면 ▼

크롤링 진행
크롤링결과1

 

약 470개 정도의 링크 페이지가 있었지만, 테스트 예제에서는 10개의 페이지만 데이터를 수집해 오도록 했습니다. 또한 서버의 부담을 줄이기 위한 페이지당 수집 대기시간을 0.5초로 해놓았는데, 실제로 사용하실 땐 더 짧게 줄이셔도 됩니다. 10개 페이지인데도 수집된 데이터양 엄청 많네요! 위 화면에 보이는 데이터의 10배 정도가 더 있답니다. 데이터를 분석 후 필요한 텍스트만 추출하도록 해야 할 거 같아요.

오늘은 이렇게 자바스크립트로 크롤링 하는 코드를 만들어봤는데요. 다음 시간에는 크롤링으로 수집한 데이터를 분석하고 텍스트 파일로 저장하는 코드를 만들어볼게요! 오늘 알아본 주의사항들을 잘 기억하시고, 항상 웹사이트의 규칙을 존중하며 작업을 진행해 주세요.  - 끝 -

웹크롤링 썸네일