이번에 회사에 입사를 하게 되면서 사내 토이 프로젝트로 뉴스 게시판을 만들기로 하였습니다.
그에 따른 준비로 뉴스 데이터를 가지고 올 웹 크롤러를 Node 기반으로 만들었는데 이 경험을 공유하고자 합니다.

📚 목차


  1. 크롤링(Crawling)이란?
  2. 필요한 Library
  3. Examples
  4. 참고한 블로그들

1. 크롤링(Crawling)이란?


Web scraping, web harvesting, or web data extraction is data scraping used for extracting data from websites. - Wiki
( 웹 스크래핑, 웹 수집 또는 웹 데이터 추출은 웹 사이트에서 데이터를 추출하기 위해 데이터를 가져오는 것을 말한다. - 위키 )

웹 크롤링(Web crawling)의 정식 명청은 Web Scraping 으로 주로 웹 페이지를 방문해서 필요한 데이터를 가져오는 것을 의미합니다. 주로 웹 크롤링에 대해 구글에 검색하면 Python을 통한 예제가 많이 나왔지만 저는 JavaScript만으로 구현하고 싶어 Node 환경에서 크롤러를 구현하는 것에 대해 조사하고 구현하였습니다.

2. 필요한 Library


제가 웹 크롤러를 구현하면서 사용한 라이브러리는 다음과 같습니다.

  • Axios : 브라우저와 Node 환경에서 사용하는 Promise 기반의 HTTP Client로 사이트의 HTML을 가져올 때 사용할 라이브러리입니다.

  • Cheerio : Node.js 환경에서 JQuery 처럼 DOM Selector 기능들을 제공합니다. Axios의 결과로 받은 데이터에서 필요한 데이터를 추출하는데 사용하는 라이브러리 입니다.

3. Examples


바로 예제로 들어가 보겠습니다.

우선 라이브러리들을 설치 합니다.

npm init -y 
npm -i --save axios cheerio

그리고 가져올 데이터를 정합니다.

저는 뉴스 기사들을 가져와 보겠습니다.

image.png

image.png

뉴스 목록에서 요소 검사를 눌러서 데이터를 가져올 HTML의 태그 이름과 Class 이름 목록을 정리합니다.

div.headlines
    ul
        li.section02

저는 headlines라는 클래스 이름을 가지고 있는 div 태그 안의 ul 태그에서 section02라는 클래스 이름을 가진 li 태그들의 데이터를 가져오기로 하였습니다.

이제 axios와 cheerio를 사용하여 데이터를 가져오는 코드를 작성해 보겠습니다.

const axios = require("axios");
const cheerio = require("cheerio");
const log = console.log;

const getHtml = async () => {
  try {
    return await axios.get("https://www.yna.co.kr/sports/all");
  } catch (error) {
    console.error(error);
  }
};

getHtml()
  .then(html => {
    let ulList = [];
    const $ = cheerio.load(html.data);
    const $bodyList = $("div.headline-list ul").children("li.section02");

    $bodyList.each(function(i, elem) {
      ulList[i] = {
          title: $(this).find('strong.news-tl a').text(),
          url: $(this).find('strong.news-tl a').attr('href'),
          image_url: $(this).find('p.poto a img').attr('src'),
          image_alt: $(this).find('p.poto a img').attr('alt'),
          summary: $(this).find('p.lead').text().slice(0, -11),
          date: $(this).find('span.p-time').text()
      };
    });

    const data = ulList.filter(n => n.title);
    return data;
  })
  .then(res => log(res));

코드를 설명 드리자면 getHtml 함수는 axios.get 함수를 이용하여 비동기로 스포츠 뉴스의 html 파일을 가져옵니다. 그 후 반환되는 Promise 객체에 cheerio를 이용하여 데이터를 가공합니다.

getHtml함수의 then 메서드의 내부 동작을 설명하기 전에 cheerio의 함수들의 기능들을 설명하겠습니다.

  • load : 인자로 html 문자열을 받아 cheerio 객체를 반환합니다.
  • children : 인자로 html selector를 문자열로 받아 cheerio 객체에서 선택된 html 문자열에서 해당하는 모든 태그들의 배열을 반환합니다.
  • each : 인자로 콜백 함수를 받아 태그들의 배열을 순회 하면서 콜백함수를 실행합니다.
  • find : 인자로 html selector 를 문자열로 받아 해당하는 태그를 반환합니다.

저는 이 cheerio의 함수들을 사용하여 뉴스의 html 페이지에서 제가 필요로 하는 뉴스 목록만을 반환 받아 log 함수로 출력하였습니다.

image.png

이로써 Node.js 환경에서 cheerio와 axios를 이용한 웹 크롤링을 해보았습니다.

4. 참고한 블로그들