티스토리 뷰
업무 자동화와 크롤링
-
- 업무 자동화란?
- 단순하고, 루틴이 정해져 있는 업무를 프로그램이나 로봇을 통해 자동화 하는것을 업무 자동화라고 부릅니다.
- 예를 들어 아래와 같습니다.
- 매 시간 0분이 될 때 마다 특정 웹 사이트에 접속해 뉴스 랭킹 1~100 위를 수집해 엑셀 파일로 만드는 일
- 매일 오전 9시에 채팅방에 똑같은 공지 메세지를 띄우는 일
- 어떻게 자동화를 할 수 있을까?
- 자동화를 한다는건 결국 프로그램으로 반복적인 작업을 처리한다는 의미입니다.
- 자동화를 하기 위해서는 업무를 할 때 필요한 무언가를 “데이터화” 하는것이 중요합니다.
- 웹 사이트에 있는 대부분을 데이터화 할 수 있도록 도와주는것이 크롤링입니다.
- 크롤링이란?
- crawl 이란 단어는 “기어가다” 혹은 “기다” 정도로 해석할 수 있습니다.
- 그럼 크롤링(Crawling)은 뭘까요? 동사이므로 “기어다니는” 정도로 해석할 수 있겠죠?
- 크롤링은 웹 사이트를 접속해 원하는 데이터를 추출해 가는것이 마치 웹 사이트를 기어다니며 정보를 수집하는것과 비슷하다고 표현되기 시작하면서 생겨났다고 추측됩니다.
- 결론적으로 크롤링을 하는 프로그램을 두고 크롤러라고 부를 수 있습니다.
- 같은 일을 하는 프로그램이지만 “Web Scraper”, “Web Robot” 등 다양한 이름을 갖고 있습니다.
- 구글이나 네이버와 같은 검색 엔진도 항상 이러한 웹 로봇을 이용해 인터넷에 존재하는 다양한 정보를 수집해 검색 결과에 포함할 수 있도록 합니다.
크롤러 프로젝트 준비
새 프로젝트 폴더 생성
이제 조금은 익숙하시겠죠? 😁
books-crawler 라는 이름으로 새 폴더를 만들어주세요!
- npm init & 필요한 패키지 설치
npm init -y
npm install axios cheerio iconv-lite
- axios: API Client처럼 HTTP 요청을 할 수 있도록 해주는 패키지입니다.
- cheerio: 웹 페이지에 있는 데이터를 쉽게 가공할 수 있도록 도와주는 패키지입니다.
- iconv-lite: 특정 웹 페이지에서는 한자, 한글, 이모지와 같은 유니코드 문자열이 깨질수 있는데, 이 경우에도 문자가 깨지지 않도록 후처리해주는 패키지입니다.
크롤링 개발 사전 지식
우리는 yes24 라는 온라인 서점에서의 베스트 셀러 순위를 수집해 볼 예정입니다!
<http://www.yes24.com/24/Category/BestSeller>
책 제목을 HTML Elements 에서 찾아보기
페이지에 접속해 개발자 도구(F12)를 열어 아래처럼 생긴 버튼을 누른 뒤 책 제목을 클릭해보세요.
화면에 보이는 요소를 HTML 구조에서 바로 찾아냈습니다!
이것을 우리는 “Element Inpect” 기능이라고 부릅니다.
Element selector를 쉽게 알아내는 방법
Element Inspect 기능으로 찾은 element 위에서 오른쪽 마우를 눌러 나오는 메뉴에서 Copy > Copy selector 를 눌러봅니다.
#bestList > ol > li.num1 > p:nth-child(3) > a
어딘가에 붙여 넣었을 때 위와 같은 값이 나온다면 정상입니다!
복사한 selector 확인해보기
현재 우리가 보고 있는 웹 페이지인 yes24는 jQuery라는 라이브러리가 불러와져 있기 때문에 아래와 같이 확인할 수 있습니다!
- 이것은 프론트엔드의 영역이기 때문이 잘 모르셔도 괜찮으니 가볍게 따라해보세요!
$("#bestList > ol > li.num1 > p:nth-child(3) > a")
- 위의 코드를 개발자 도구의 Console 탭에 넣고 실행해보면 아래와 같이 Element를 찾게 됩니다.
- 모든 목록의 값을 가져올 수는 없을까요?
그걸 위해서는 해당 페이지의 HTML이 어떤 구조로 작성되어 있는지 거시적으로 볼 수 있어야 합니다. 다행히 yes24는 구조가 매우 간단해서 아래와 같이 ol 태그 하위에 li 태그가 나열된 상태입니다.
- 그럼 모든 목록을 가져오기 위해서는?
이전에 사용했던 Element selector를 조금만 수정하면 됩니다.
.num1 이라는 값은 class=”num1” 속성을 가진 Element를 뜻하므로 아래와 같이 간단히 수정해보겠습니다.
$("#bestList > ol > li > p:nth-child(3) > a")
크롤러 구현 (1)
API Client로 크롤링 할 웹 페이지 살펴보기
<http://www.yes24.com/24/Category/BestSeller>
Thunder Client를 이용해 요청을 보내보면 아래처럼 확인할 수 있습니다!
우리는 이제 Thunder Client로 확인할 수 있는 데이터를 axios 라는 패키지를 이용해 가져올 예정입니다.
axios 모듈을 이용해 HTML 데이터 가져오기
- axios 모듈은 API Client처럼 HTTP 요청을 해 응답 값을 받아와주는 역할을 합니다.
- 아래의 형태로 사용할 수 있습니다.
const axios = require("axios");
axios({
url: "주소",
method: "GET",
})
.then((response) => {
console.log(response.data);
});
index.js 예시
const axios = require("axios");
axios({
url: "<http://www.yes24.com/24/Category/BestSeller>",
method: "GET",
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
iconv-lite 모듈을 이용해 문자가 깨지는 문제 해결
EUC-KR로 인코딩 되어 있는 문자열(한글)을 UTF-8로 Decode해줍니다.
이런 인코딩 문제는 해당 서비스를 제공하는 웹 서버가 어떤 형식으로 데이터를 인코딩하여 저장하는지에 따라 문제 발생 여부가 다릅니다.
- iconv-lite 모듈은 Buffer라는 데이터 형식을 입력받습니다.
axios는 responseType: "arraybuffer" 라는 옵션을 추가하면 응답 데이터를 Buffer로 사용할 수 있게 해줍니다!
- 모듈은 아래와 같은 형식으로 사용할 수 있습니다.
const iconv = require("iconv-lite");
console.log(iconv.decode(bufferData, "EUC-KR").toString());
ndex.js 예시
const axios = require("axios");
const iconv = require("iconv-lite");
axios({
url: "<http://www.yes24.com/24/Category/BestSeller>",
method: "GET",
**responseType: "arraybuffer",**
})
.then((response) => {
**const content = iconv.decode(response.data, "EUC-KR").toString();**
console.log(content);
})
.catch((error) => {
console.log(error);
});
크롤러 구현 (2)
cheerio 모듈을 이용해 원하는 Element에 있는 값 추출
- cheerio는 HTML의 Element를 Query Selector라는 방법으로 선택해 가져올 수 있도록 해주는 패키지입니다.
- yes24 웹 사이트에서 잠깐 맛본 그거 맞습니다!
- 이렇게 가져온 Element는 손쉽게 원하는 데이터를 추출해 낼 수 있기 때문에 크롤링 할 때에는 항상 사용된다고 봐도 무방합니다.
- cheerio는 기본적으로 아래와 같이 사용할 수 있습니다.
const cheerio = require('cheerio');
const $ = cheerio.load('<h2 class="title">Hello world</h2>');
$('h2.title').text(); // Print: "Hello world"
- 또한 아래와 같이 each 메서드를 제공하는데, Element 객체를 하나하나 접근할 수 있기 때문에 이번 시간에 유용하게 사용할 수 있습니다
$.each((index, element) => { ... });
index.js 예시
const cheerio = require("cheerio");
const axios = require("axios");
const iconv = require("iconv-lite");
axios({
url: "<http://www.yes24.com/24/Category/BestSeller>",
method: "GET",
responseType: "arraybuffer",
})
.then((response) => {
const content = iconv.decode(response.data, "EUC-KR").toString();
**const $ = cheerio.load(content);
const bestList = $("#bestList > ol > li > p:nth-child(3) > a");
bestList.each((index, element) => {
console.log(element.text());
});**
})
.catch((error) => {
console.log(error);
});
책의 제목, 설명, 이미지 주소, 가격 모두 추출하기
특정 Element의 하위를 다시 탐색하는 방법은 아래와 같습니다.
$(element).find("p:nth-child(3) > a")
특정 Element의 Attribute를 찾는 방법은 아래와 같습니다.
$('<img src="image url" />').attr("src");
// Print: "image url"
index.js 예시
const axios = require("axios");
const iconv = require("iconv-lite");
const cheerio = require("cheerio");
axios({
url: "<http://www.yes24.com/24/Category/BestSeller>",
method: "GET",
responseType: "arraybuffer",
})
.then((response) => {
const content = iconv.decode(response.data, "EUC-KR").toString();
**const $ = cheerio.load(content);
const bestList = $("#bestList > ol > li");
bestList.each((index, element) => {
const title = $(element).find("p:nth-child(3) > a").text();
const desc = $(element).find("p.copy > a").text();
const image = $(element).find("p.image > a > img").attr("src");
const price = $(element).find("p.price > strong").text();
});**
})
.catch((error) => {
console.log(error);
});
마무리
- 우리는 웹에 있는 데이터를 우리가 마음대로 다룰 수 있도록 데이터화 할 수 있게 되었어요!
- 이렇게 긁어 온 데이터는 데이터베이스에 저장해도 되고, 저장하지 않고 매번 API 요청을 받았을 때 응답 값으로 반환하도록 해도 된답니다.
'항해 > 주특기 1주차' 카테고리의 다른 글
[node js] 5주차 -3 (0) | 2022.01.27 |
---|---|
[node js] 5주차 -1 (0) | 2022.01.27 |
[node js] 4주차 -4 (0) | 2022.01.27 |
[node js] 4주차 -3 (0) | 2022.01.23 |
[node js] 4주차 -2 (0) | 2022.01.23 |