사이드 프로젝트로 크롤링을 해본적은 있다. 그냥 단순한 웹사이트 하나를 크롤링하는 로직이였는데 이걸 처음 만들때는 참 애를 많이 먹었다.
여기서 다루는 크롤러는 당연히 저렇게 단순한게 아니고 검색엔진을 만들기 위해 전세계 모든 웹사이트를 돌아다니며 정보를 수집하는 크롤러를 만드는 예시를 보여준다.
일단 크롤링은 어디에 사용할 수 있을까.
뭐 다이어그램적인 설계는 이해하기 쉬운 편이다. 그럼 일단 각 요소에 대해 어떤 기능을 수행하는지 알아보고 크롤러의 작업 흐름을 한번 살펴 보자.
크롤링의 시작점이다. 어떤 대학 웹사이트로 부터 시작하면 이 사이트에 붙어있는 여러 하이퍼링크의 웹사이트를 크롤링하는 방식이다. 일반적으로 해당 대학의 도메인 이름이 붙은 모든 페이지의 url을 시작 url로 사용한다.
대부분의 현대적 웹 크롤러는 크롤링 상태를 다운로드할 url,다운로드된 url의 두가지 상태로 나눠 관리한다. 이 중 '다운로드할 url'을 저장 관리하는 컴포넌트를 미수집 url 저장소라고 부른다. FIFO큐라고 생각하면 된다.
url을 ip 주소로 변환하는 절차가 필요하다.html 다운로더는 도메인 이름 변환기를 사용해 url에 대응하는 ip주소를 알아낸다. 쉽게 말해서 url을 통해 연결되있는 dns를 한번 타고 여기에 연결되어 있는 ip주소를 따오는 방식이다.
일단 웹 페이지를 다운로드하면 파싱과 검증을 거쳐야 한다. 이상한 웹페이지라면 걸러야하기 때문이다. 따라서 일종의 로직을 작성해 콘텐츠가 정상적인지 확인하고 파싱을 해야한다.
그리고 크롤링 서버 안에 콘텐츠 파서를 만들만 좋지 않다. 콘텐츠 파싱이라는 작업 자체가 좀 무거운 작업이될 가능성이 높기 때문에 이는 별도의 컴포넌트로 만드는 것이 바람직하다.
웹에 공개된 연구 결과에 따르면,29% 가량의 웹페이지 콘텐츠는 중복이다.
날로먹는 애들이 많다는 뜻이다. 고로 우리는 같은 콘텐츠를 여러번 저장하게 될 가능성이 크다. 따라서 이를 잘 걸러내는 로직이 필요하다. 가장 간단한 방법은 두 html 문서를 열로 보고 비교하는 것이지만 이는 너무 무거운 작업이 된다. 효과적인 방법은 웹페이지의 해시 값을 비교하는 것이라고 한다.
크롤링을 잘 했다면 잘 저장해야 한다. 요구 사항에 맞는 저장소를 사용하고 필요한 구조로 잘 저장하면 될 것이다. 대략적으로 아래의 두가지만 신경 쓰면 될듯 하다.
URL추출기는 html페이지를 파싱해서 안에 있는 다른 페이지로 향하는 url들을 골라내는 역할을 한다. 일반적으로 상대링크로 되어 있는 링크들을 절대 링크로 바꾸어 추출한다. 예를들어 www.naver.com의 하위 링크인 /user1 이라는 링크가 있다고 치면 www.naver.com/user1로 변환한다.
특정 콘텐츠 타입이나 파일 확장자를 갖는 url. 접속시 오류가 발생하는 url, 접근 제외 목록에 포함된 url등을 크롤링 대상에서 배제하는 역할을 한다.
이를 구현하기 위해서는 이미 방문한 url이나 미수집 url 저장소에 보관된 url을 추적할 수 있도록 자료 구조를 사용하면 된다. 이미 방문한 적 있는 url인지 추적하면 같은 url을 여러번 처리하는 일을 방지할 수 있으므로 서버 부하를 줄이고 같은 url을 여러번 처리하는 일을 방지할 수 있다.
이미 방문한 url을 보관하는 저장소다.
위에 그림을 다시 봐보자.
대략적인 흐름은 이 그림의 흐름과 같다.
위와 같은 방식으로 크롤러는 작동한다. 다음에는 좀 더 세부적으로 크롤러의 설계에 대해 알아보자