JavaScript 웹 크롤링 하기
11 Jun 2019목차
- 사전 준비
- 크롤러 구현
- 참고 자료
1. 사전 준비
1.1. npm 설치 및 프로젝트 시작하기 먼저 npm이 무엇인지 알아보자. npm은 node package manager를 의미하며 Java의 gradle 혹은 Python의 pip과 유사한 패키지 관리자이다.
https://nodejs.org/en/download/ 에서 운영체제별 인스톨러를 설치할 수 있다.
다음으로 package.json 파일을 생성해 보자.
npm init
묻는 내용에 일단은 계속 엔터를 치고 넘어가면 npm에 의해 개발 환경이 생성된다. 이후 npm을 통해 설치하는 모든 라이브러리들은 node_modules라는 디렉토리에 저장되며, package.json을 통해 관리할 수 있다.
1.2. 관련 라이브러리 설치
먼저 크롤러를 만들기 위해 필요한 라이브러리들을 정리해 보자.
우리는 axios와 cheerio를 사용해 크롤링을 할 것이다.
axios는 자바스크립트를 이용해 AJAX 리퀘스트를 할 수 있는 라이브러리이다. AJAX란 Asynchronous JavaScript and XML을 의미하는 것으로 비동기적으로 JSON이나 XML 등의 데이터를 받을 수 있는 방법을 의미한다.
cheerio는 JQuery처럼 DOM Selector 기능을 제공한다. axios로 받은 HTML 데이터에서 실제로 필요한 정보를 발라내는 데 사용할 것이다. 참고로, cheerio는 Python의 BeautifulSoup과 유사한 기능을 한다.
npm i axios cheerio
2. 크롤러 구현
2.1. axios와 cheerio import
이제 본격적으로 크롤러를 구현해보자.
const axios = require("axios");
const cheerio = require("cheerio");
먼저 axios와 cheerio를 import한다. Node는 require 함수의 인자를 node_modules에서 부터 디렉토리 명으로 검색하므로 구체적인 경로를 적지 않아도 설치한 라이브러리는 간단하게 import 할 수 있다.
2.2. 크롤링 대상 사이트 분석
다음으로 크롤링 하고자 하는 사이트를 살펴보자.
윤리적인 이유에서 본인의 블로그를 대상으로 한 크롤러를 짜 보고자 한다. chaewonkong.github.io에서 포스트 제목들을 가져오도록 해 보자.
body > main > div > section > ul > li > article > h2 > a
우리가 가져오고자 하는 포스트 제목들은 위와 같은 DOM 구조를 이루고 있다.
2.3. 코드 작성
이제 대충 구조를 알았으니 코드를 작성해 보자.
scraper.js
const axios = require("axios");
const cheerio = require("cheerio");
// axios를 활용해 AJAX로 HTML 문서를 가져오는 함수 구현
async function getHTML() {
try {
return await axios.get("https://chaewonkong.github.io");
} catch (error) {
console.error(error);
}
}
// getHTML 함수 실행 후 데이터에서
// body > main > div > section > ul > li > article > h2 > a
// 에 속하는 제목을 titleList에 저장
getHTML()
.then(html => {
let titleList = [];
const $ = cheerio.load(html.data);
// ul.list--posts를 찾고 그 children 노드를 bodyList에 저장
const bodyList = $("ul.list--posts").children("li.item--post");
// bodyList를 순회하며 titleList에 h2 > a의 내용을 저장
bodyList.each(function(i, elem) {
titleList[i] = {
title: $(this)
.find("h2 a")
.text()
};
});
return titleList;
})
.then(res => console.log(res)); // 저장된 결과를 출력
2.4. 실행
자 이제 코드를 실행해 보자.
node scraper.js
아래는 위 파일을 실행했을 경우의 결과다.
[
{ title: "Simple Chat App - React with Socket.IO" },
{ title: "Sort method in JavaScript" },
{ title: "Object Oriented Programming 1 - Basic Concepts" },
{ title: "웹과 HTTP" },
{ title: "DOM과 Object Model" },
{ title: "Node.js의 특징" },
{ title: "사이트 간 스크립팅" },
{ title: "파이썬(Python) 데코레이터(Decorator)" },
{ title: "카운팅 정렬(계수정렬, Counting Sort) - 백준 알고리즘 10989번" },
{ title: "그래프를 활용한 알고리즘 01 - PICNIC" },
{ title: "자바스크립트에서 클로저 사용하는 법" },
{ title: "분할정복을 이용한 자바스크립트 병합정렬 알고리즘" },
{
title:
"반응형(Responsive) 웹과 적응형(Adaptive) 웹, 그리고 모바일 퍼스트 디자인"
},
{ title: "ES 2017 async와 await 사용법" },
{ title: "자바스크립트 알고리즘 - n개의 원소 중 m개를 뽑는 모든 조합" },
{ title: "리액트(React)란 무엇인가" },
{ title: "Express 서버와 React: Proxy 활용과 빌드 및 헤로쿠(Heroku) 배포" },
{ title: "N 팩토리얼에서 1의자리부터 연속하는 0의 개수 구하기" },
{ title: "자바스크립트 이진탐색 알고리즘" },
{ title: "타입스크립트(TypeScript)의 타입들" },
{ title: "자바스크립트의 배열(Array in JavaScript)" },
{ title: "자바스크립트 함수 내 객체의 변경과 할당" },
{ title: "쿠키(Cookie) 기반의 사용자 인증(Auth)" },
{ title: "파이썬 이진탐색 알고리즘" },
{ title: "JavaScript 참조 타입과 원시 타입" },
{ title: "트랜스컴파일러(바벨)의 목적과 사용법" },
{ title: "React & Redux 1" },
{ title: "파이썬으로 웹 크롤러 만들기 2" },
{ title: "파이썬으로 웹 크롤러 만들기 1" }
];
이처럼 간단하게 Node.js와 axios, cheerio를 이용해 크롤러를 구현해 보았다.
Node.js에서도 excel 파일로 크롤링한 정보를 파싱(Parsing)하는 방법이 존재하고, 그런 라이브러리가 있다.
이 부분은 다음에 다뤄보기로 하고, 오늘은 이만 마치고자 한다.