매일 업데이트
2022-11-21 18:30 8 min

JavaScript에서 웹 스크래핑 시작하기

웹 스크래핑은 프로그래밍 세계에서 매우 매력적인 분야 중 하나입니다.

그렇다면 웹 스크래핑이란 정확히 무엇일까요?

왜 이런 기술이 필요한 걸까요?

함께 그 해답을 찾아봅시다.

웹 스크래핑의 개념

웹 스크래핑은 웹사이트에서 데이터를 자동으로 수집하는 과정을 의미합니다.

웹 스크래핑은 다양한 분야에서 활용됩니다. 예를 들어, 온라인 쇼핑몰의 제품 가격 정보를 추출하여 다른 플랫폼과 비교하거나, 웹에서 매일 주식 시세를 가져오는 데 사용됩니다. 심지어 구글이나 야후와 같은 자체 검색 엔진을 구축하는 데도 활용될 수 있습니다. 이 외에도 웹 스크래핑은 무궁무진한 가능성을 가지고 있습니다.

웹사이트에서 데이터를 추출하는 방법을 이해하게 되면, 수집한 데이터를 바탕으로 다양한 작업을 수행할 수 있습니다.

웹사이트 데이터를 추출하는 프로그램을 '웹 스크레이퍼'라고 부릅니다. 이 글에서는 JavaScript를 사용하여 웹 스크레이퍼를 작성하는 방법을 알아볼 것입니다.

웹 스크래핑은 크게 두 단계로 나눌 수 있습니다.

  • HTTP 요청 라이브러리나 헤드리스 브라우저를 사용하여 웹페이지의 원시 데이터를 가져옵니다.
  • 가져온 데이터를 분석하여 필요한 특정 정보를 추출합니다.

이제 본격적으로 시작해 보겠습니다.

프로젝트 환경 설정

만약 NodeJS 설치 가이드를 아직 확인하지 않았다면, NodeJS가 이미 설치되어 있다고 가정하겠습니다.

JavaScript를 이용한 웹 스크래핑을 위해 'node-fetch'와 'cheerio' 패키지를 사용할 것입니다. npm을 이용하여 프로젝트를 설정하고, 외부 패키지를 연동하는 과정을 살펴보겠습니다.

설정 과정을 간략하게 정리하면 다음과 같습니다.

  • 'web_scraping'이라는 새로운 디렉터리를 만들고 해당 디렉터리로 이동합니다.
  • 'npm init' 명령을 실행하여 프로젝트를 초기화합니다.
  • 질문에 따라 적절한 답변을 입력합니다.
  • 다음 명령을 실행하여 필요한 패키지를 설치합니다.
npm install node-fetch cheerio

설치된 패키지들에 대해 자세히 알아봅시다.

node-fetch

node-fetch 패키지는 Node.js 환경에서 'window.fetch'와 유사한 기능을 제공합니다. HTTP 요청을 생성하고 서버로부터 원시 데이터를 받아오는 데 도움을 줍니다.

cheerio

cheerio 패키지는 가져온 원시 데이터에서 필요한 정보를 분석하고 추출하는 데 사용됩니다. cheerio 공식 웹사이트에서 더 자세한 정보를 확인할 수 있습니다.

node-fetch와 cheerio 두 패키지만으로도 JavaScript를 이용한 웹 스크래핑을 충분히 수행할 수 있습니다. 여기서는 모든 기능을 다루지 않고, 웹 스크래핑의 전반적인 흐름과 각 단계에서 가장 유용한 기능에 초점을 맞출 것입니다.

웹 스크래핑을 시작해 봅시다!

크리켓 월드컵 정보 스크래핑

이 섹션에서는 실제 웹 스크래핑을 진행할 것입니다.

어떤 데이터를 추출할까요?

섹션 제목에서 쉽게 짐작할 수 있듯이, 역대 크리켓 월드컵 우승팀과 준우승팀 정보를 추출해 보겠습니다.

  • 프로젝트 폴더에 'extract_cricket_world_cups_list.js' 파일을 생성합니다.
  • 위키백과 크리켓 월드컵 페이지에서 필요한 정보를 얻을 수 있습니다.
  • 먼저 'node-fetch' 패키지를 사용하여 웹페이지의 원시 데이터를 가져옵니다.
  • 아래 코드는 위키백과 페이지의 원시 데이터를 가져오는 방법을 보여줍니다.
const fetch = require("node-fetch");

// 원시 데이터를 가져오는 함수
const getRawData = (URL) => {
  return fetch(URL)
    .then((response) => response.text())
    .then((data) => {
      return data;
    });
};

// 데이터 URL
const URL = "https://en.wikipedia.org/wiki/Cricket_World_Cup";

// 메인 함수
const getCricketWorldCupsList = async () => {
  const cricketWorldCupRawData = await getRawData(URL);
  console.log(cricketWorldCupRawData);
};

// 메인 함수 호출
getCricketWorldCupsList();

이제 URL에서 원시 데이터를 가져왔습니다. 다음 단계는 이 원시 데이터에서 필요한 정보를 추출하는 것입니다. 이때 'cheerio' 패키지를 활용합니다.

cheerio를 사용하여 HTML 태그와 관련된 데이터를 추출하는 것은 매우 간단합니다. 본격적인 데이터 추출에 앞서, cheerio를 이용한 간단한 데이터 분석 예시를 먼저 살펴보겠습니다.

  • 'cheerio.load' 메소드를 사용하여 HTML 데이터를 분석합니다.
const parsedSampleData = cheerio.load(
      `<div id="container"><p id="title">I'm title</p></div>`
   );
  • 위의 HTML 코드를 분석했습니다. 여기서 p 태그의 내용을 추출하려면 어떻게 해야 할까요? JavaScript DOM 조작에서 사용하는 것과 동일한 선택자를 이용하면 됩니다.

console.log(parsedSampleData("#title").text());

원하는 대로 태그를 선택하여 데이터를 추출할 수 있습니다. 더 다양한 방법은 cheerio 공식 웹사이트에서 확인할 수 있습니다.

  • 이제 크리켓 월드컵 목록을 추출할 차례입니다. 먼저 추출하려는 정보가 있는 HTML 태그를 찾아야 합니다. 크리켓 월드컵 위키백과 페이지에서 페이지 검사를 통해 해당 HTML 태그 정보를 확인합니다.

다음은 전체 코드입니다.

const fetch = require("node-fetch");
const cheerio = require("cheerio");

// 원시 데이터를 가져오는 함수
const getRawData = (URL) => {
  return fetch(URL)
    .then((response) => response.text())
    .then((data) => {
      return data;
    });
};

// 데이터 URL
const URL = "https://en.wikipedia.org/wiki/Cricket_World_Cup";

// 메인 함수
const getCricketWorldCupsList = async () => {
  const cricketWorldCupRawData = await getRawData(URL);

  // 데이터 분석
  const parsedCricketWorldCupData = cheerio.load(cricketWorldCupRawData);

  // 테이블 데이터 추출
  const worldCupsDataTable = parsedCricketWorldCupData("table.wikitable")[0]
    .children[1].children;

  console.log("Year --- Winner --- Runner");
  worldCupsDataTable.forEach((row) => {
    // `td` 태그 추출
    if (row.name === "tr") {
      let year = null,
        winner = null,
        runner = null;

      const columns = row.children.filter((column) => column.name === "td");

      // 년도 추출
      const yearColumn = columns[0];
      if (yearColumn) {
        year = yearColumn.children[0];
        if (year) {
          year = year.children[0].data;
        }
      }

      // 우승팀 추출
      const winnerColumn = columns[3];
      if (winnerColumn) {
        winner = winnerColumn.children[1];
        if (winner) {
          winner = winner.children[0].data;
        }
      }

      // 준우승팀 추출
      const runnerColumn = columns[5];
      if (runnerColumn) {
        runner = runnerColumn.children[1];
        if (runner) {
          runner = runner.children[0].data;
        }
      }

      if (year && winner && runner) {
        console.log(`${year} --- ${winner} --- ${runner}`);
      }
    }
  });
};

// 메인 함수 호출
getCricketWorldCupsList();

스크래핑된 데이터는 다음과 같습니다.

Year --- Winner --- Runner
1975 --- West Indies --- Australia
1979 --- West Indies --- England
1983 --- India --- West Indies
1987 --- Australia --- England
1992 --- Pakistan --- England
1996 --- Sri Lanka --- Australia
1999 --- Australia --- Pakistan
2003 --- Australia --- India
2007 --- Australia --- Sri Lanka
2011 --- India --- Sri Lanka
2015 --- Australia --- New Zealand
2019 --- England --- New Zealand

정말 멋지지 않나요? 😎

스크래핑 템플릿

URL에서 원시 데이터를 가져오는 과정은 모든 웹 스크래핑 프로젝트에서 공통적으로 사용됩니다. 데이터 추출 부분만 요구사항에 따라 변경될 뿐입니다. 아래 코드를 템플릿으로 활용할 수 있습니다.

const fetch = require("node-fetch");
const cheerio = require("cheerio");
const fs = require("fs");
// 원시 데이터를 가져오는 함수
const getRawData = (URL) => {
  return fetch(URL)
    .then((response) => response.text())
    .then((data) => {
      return data;
    });
};
// 데이터 URL
const URL = "https://example.com/";
// 메인 함수
const scrapeData = async () => {
  const rawData = await getRawData(URL);
  // 데이터 분석
  const parsedData = cheerio.load(rawData);
  console.log(parsedData);
  // 데이터 추출 코드 작성
  // 여기
  // ...
  // ...
};
// 메인 함수 호출
scrapeData();

결론

웹페이지에서 데이터를 스크래핑하는 방법을 배우셨습니다. 이제 코딩을 통해 실력을 향상시켜 보세요.

또한 클라우드 기반 웹 스크래핑 솔루션이나 다른 웹 스크래핑 프레임워크도 살펴보는 것을 추천합니다.

즐거운 코딩하세요! 🙂

이 글이 흥미로우셨나요? 다른 사람들과 공유해보시는 건 어떠세요?

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.