[Node.js] SCRAPING을 위한 cheerio 모듈과 cheerio-httpcli 모듈[Node.js] SCRAPING을 위한 cheerio 모듈과 cheerio-httpcli 모듈
Posted at 2019. 5. 8. 16:59 | Posted in Node.js발췌 : 자바스크립트와 Node.js를 이용한 웹 크롤링 테크닉
※ 스크래핑이란?
-. 웹의 세계에서 흔히 말하는 '스크래핑'은 웹 사이트에서 HTML 데이터를 수집하고, 특정 데이터를 추출, 가공하여 저장하는것을 말한다.
-. 단순히 웹 사이트에서 HTML 파일을 다운로드만 하는 것이 아니라 그 HTML 파일의 각 요소들을 분석하는 과정을 포함한다.
■ cheerio 모듈과 cheerio-httpcli 모듈에 관하여
-. cheerio 모듈을 사용하면 HTML / XML 데이터에 대해 jQuery(제이쿼리)처럼 임의의 요소를 획득하여 조작할 수 있다.
-. cheerio모 듈 이것을 이용한 것이 cheerio-httpchli 모듈이다.
-. cheerio-httpchli 모듈은 cheerio 모듈에서 웹 페이지 취득 기능을 추가한 것이다.
모듈 | 설 명 |
cheerio |
· 웹 API나, cheerio-httpchli등으로이미 취득한 데이터에서 임의의 데이터를 가져오는 경우 사용 |
cheerio-httpchli |
· 웹 페이지를 취득하는 경우 cheerio-httpchli 모듈을 사용 |
■ cheerio 모듈
#01. cheerio 모듈 설치
$ npm install cheerio |
|
#02. cheerio 모듈의 기본적인 사용방법
XML 데이터로부터 책의 제목 일람을 표시해 보자.
# 소스코드
xml_title_list.js |
// 모듈을 로드함 const cheerio = require( "cheerio" ); // 샘플 XML 데이터 var xml = "<books>"; xml += "<book><title>반쪽달이 떠오르는 하늘</title><author>하시모토 츠무구</author></book>"; xml += "<book><title>렌탈 마법사</title><author></author>산다 마코토</book>"; xml += "<book><title>강각의 레기오스</title><author>아마기 슈스케</author></book>";var xml += "<books>"; // load( )를 메소드를 통해 XML 데이터를 읽음 var data = cheerio.load( xml ); // 책의 제목 일람을 표시 data( "title" ).each(function( key, val ) {
// each( ) 메서드의 인자로 주어지는 객체 변수 val 자체에는 text( ) 메서드가 존재하지 않는다. // console.log( val.text() ); ← 에러발생 // // 따라서 아래와 같이 data(val).text( ); 라고 기술해야 한다. var bookTitle = data( val ).text(); console.log( bookTitle ); }); |
#03. 취득한 요소의 자식 요소 검사하기
지금부터는 여러 가지 프로그램을 작성하여 동작을 검증해 보자.
# XML 데이터
light_novel.xml |
<books> <book id="ex001"> <title>이스캐리엇</title> <author>산다 마코토</author> <price value="5900"/> <options> <color>BLACK</color> </options> </book> <book id="ex002"> <title>문학소녀</title> <author>노무라 미즈키</author> <price value="6800"/> <options> <color>GREEN</color> </options> </book> <book id="nt001"> <title>사신의 발라드</title> <author>하세가와 케이스케</author> <price value="6000"/> <options> <color>WHITE</color> </options> </book> <book id="nt002"> <title>스즈미야 하루히</title> <author>타니가와 나가루</author> <price value="7000"/> <options> <color>BLUE</color> </options> </book> <book id="nt003"> <title>작안의 샤나</title> <author>타카하시 야시치로</author> <price value="7000"/> <options> <color>RED</color> </options> </book> <book id="j001"> <title>제로의 사역마</title> <author>야마구치 노보루</author> <price value="6800"/> <options> <color>PINK</color> </options> </book> <book id="j002"> <title>소드 아트 온라인</title> <author>카와하라 레지</author> <price value="7000"/> <options> <color>AZURE</color> </options> </book> </books> |
# 소스코드
show_books_title.js |
// 모듈을 로드함 const cheerio = require( "cheerio" ); const fs = require( "fs" ); // 샘플 XML 데이터를 cheerio로 읽어들임 var xml = fs.readFileSync( "light_novel.xml", "utf-8" ); // load( )를 메소드를 통해 XML 데이터를 읽음 var data = cheerio.load( xml ); // 책의 정보를 표시 // children( ) 메서드를 사용하여 <book> 요소의 자식 요소를 다루고 있다. data( "book" ).each(function( key, val ) {
// <book> 태그 자식요소로부터 값을 취득 var bookTitle = data( val ).children( "title" ).text( ); var bookAuthor = data( val ).children( "author" ).text( );
console.log( bookTitle + " - " + bookAuthor ); }); |
#04. 속성값 가져오기
show_books_price.js |
// 모듈을 로드함 const cheerio = require( "cheerio" ); const fs = require( "fs" ); // 샘플 XML 데이터를 cheerio로 읽어들임 var xml = fs.readFileSync( "light_novel.xml", "utf-8" ); // load( )를 메소드를 통해 XML 데이터를 읽음 var data = cheerio.load( xml ); // 책의 정보를 표시 data( "book" ).each(function( key, val ) {
// ID 속성 취득 var bookId = data( val ).attr( "id" );
// <price> 태그의 value 속성 취득 var bookPrice = data( val ).children( "price" ).attr( "value" );
console.log( bookId + " : " + bookPrice ); }); |
show_books_color.js |
// 모듈을 로드함 const cheerio = require( "cheerio" ); const fs = require( "fs" ); // 샘플 XML 데이터를 cheerio로 읽어들임 var xml = fs.readFileSync( "light_novel.xml", "utf-8" ); // load( )를 메소드를 통해 XML 데이터를 읽음 var data = cheerio.load( xml ); // 책의 제목과 색을 표시 data( "book" ).each(function( key, val ) {
// <book> 태그 자식요소로부터 책의 제목 값을 취득 var bookTitle = data( val ).children( "title" ).text( );
// <book> 태그 자손요소로부터 책의 색상 값을 취득 var bookColor = data( val ).find( "color" ).text( );
console.log( bookTitle + " : " + bookColor ); }); |
#06. 테이블 내의 정보 가져오기
marvel.html |
<html> <head> <title>:: Marvel's The Avengers ::</title> </head> <body> <table id="avenger"> <thead> <tr><th>히어로</th><th>이름</th><th>배우</th></tr> </thead> <tbody> <tr><td>아이언맨</td><td>토니 스타크</td><td>로버트 다우니 주니어</td></tr> <tr><td>캡틴 아메리카</td><td>스티브 로저스</td><td>크리스 에반스</td></tr> <tr><td>토르</td><td>토르 오딘슨</td><td>크리스 헴스워스</td></tr> <tr><td>헐크</td><td>브루스 배너</td><td>마크 러팔러</td></tr> <tr><td>블랙 위도우</td><td>나타샤 로마노프</td><td>스칼렛 요한슨</td></tr> <tr><td>호크 아이</td><td>클린트 바튼</td><td>제러미 레너</td></tr> <tr><td>워머신</td><td>제임스 로즈</td><td>돈 치들</td></tr> <tr><td>팔콘</td><td>샘 윌슨</td><td>앤서니 매키</td></tr> <tr><td>윈터 솔저</td><td>버키 반즈</td><td>세바스찬 스탠</td></tr> <tr><td>퀵 실버</td><td>피에트로 막시모프</td><td>에런 테일러존슨</td></tr> <tr><td>스칼렛 위치</td><td>완다 막시모프</td><td>엘리자베스 올슨</td></tr> <tr><td>비전</td><td>완다 막시모프</td><td>폴 베타니</td></tr> <tr><td>스파이더맨</td><td>피터 파커</td><td>톰 홀랜드</td></tr> <tr><td>블랙 팬서</td><td>트찰라</td><td>채드웍 보스만</td></tr> <tr><td>닥터 스트레인지</td><td>스티븐 스트레인지</td><td>베네딕트 컴버배치</td></tr> </tbody> </table> </body> </html> |
# 소스코드
read_table.js |
// 모듈을 로드함 const cheerio = require( "cheerio" ); const fs = require( "fs" ); // marvel.html 파일을 읽어들임 var html = fs.readFileSync( "marvel.html", "utf-8" ); // load( )를 메소드를 통해 HTML 데이터를 읽음 $ = cheerio.load( html ); // 테이블 취득 var data = readTable( "#avenger" ); console.log( data ); // 테이블의 전체 셀을 읽음, table 태드를 읽어들여 2차원 배열 변수로 반환한다. function readTable( query ) { var data = [ ]; var table = $( query ); var tr_list = $( table ).children( "tbody" ).children( "tr" ); // 행의 갯수만큼 반복문을 실행 for( var row = 0; row < tr_list.length; row++ ) {
var cells = tr_list.eq( row ).children( ); var cols = [ ];
// 열의 갯수만큼 반복문을 실행 for( var column = 0; column < cells.length; column++ ) {
var hero = cells.eq( column ).text( ); cols.push( hero ); }
data.push( cols ); }
return data; } |
■ cheerio-httpcli 모듈
-. Node.js를 사용하용 스크래핑할 때 편리한 모듈이 cheerio-httpcli다.
-. cheerio-httpcli 모듈을 사용하면 파일을 손쉽게 다운로드 할 수 있을 뿐 아니라 jQuery(제이쿼리)와 비슷하게 요소를 획득할 수 있다.
-. 페이지 안의 데이터를 꺼낼 때 간편하게 지정한 요소를 추출할 수 있는 점이 가장 큰 장점이다.(웹 페이지의 문자 코드도 자동으로 판정하여 읽어 준다.)
-. 페이지 안의 링크나 이미지를 쉽게 추출할 수 있다.
#01. cheerio-httpcli 모듈 설치
$ npm install cheerio-httpcli |
#02. HTML 파일 다운로드
# 소스 코드
getpage.js |
// 모듈 로드 const client = require( "cheerio-httpcli" ); // 다운로드 const url = "http://magic.wickedmiso.com"; const param = { }; // fetch( ) 메서드의 인자는 URL, 파라미터, 콜백 함수의 순서로 지정한다. client.fetch( url, param, function( error, data, response ) {
// 에러체크 if( error ) { console.error( "Error : ", error ); return; }
// 다운로드한 결과를 화면에 출력 var body = data.html( ); console.log( body ); }); |
※ fetch( ) 메서드
-. fetch( ) 메서드의 인자는 URL, 파라미터, 콜백 함수의 순서로 지정한다.
-. 콜백 함수는 웹사이트에서 데이터 취득이 완료된 시점에서 실행한다.
-. 콜백함수의 인자로는 오류 정보( error ), 취득한 데이터( data ), 서버의 응답 정보( response ), 이렇게 세가지가 주어진다.
#03. HTML 파일에서 링크 추출
cheerio-httpcli 모듈은 웹에서 HTML을 내려받은 뒤 CSS 선택자를 통해 임의의 요소를 추출하는데 사용한다.
이번에는 HTML에 링크된 URL 목록을 출력하는 프로그램을 만들어 보자.
show-link.js |
// 모듈 로드 const client = require( "cheerio-httpcli" ); // 다운로드 const url = "http://jpub.tistory.com"; const param = { }; client.fetch( url, param, function( error, data, response ) {
// 에러체크 if( error ) { console.error( "Error : ", error ); return; }
// 링크를 추출하여 표시 data( "a" ).each(function( idx ) {
var text = data( this ).text( ); var href = data( this ).attr( "href" );
console.log( text + " : " + href ); }); }); |
-. fetch( ) 메서드의 콜백 함수의 두번째 인자로 $를 지정하였는데, 이를 통해 jQuery처럼 페이지의 특정 요소를 추출할 수 있게 된다.
( $("a")라고 쓰면 HTML 문서 내의 모든 <a> 태그의 내용을 추출한다. )
-. each( ) 메서드를 통해 추출한 각 요소들에 대해 지정한 함수를 수행한다.
-. 추출한 각 요소의 텍스트 부분과 href 속성의 값을 콘솔에 출력한다.
#04. HTML 파일에서 링크 추출 - 상대 URL을 절대 URL로 변경
show-link-path.js |
// 모듈 로드 const client= require( "cheerio-httpcli" ); const urlType = require( "url" ); // 다운로드 const url = "http://jpub.tistory.com"; const param = { }; client.fetch( url, param, function( error, data, response ) {
// 에러체크 if( error ) { console.error( "Error : ", error ); return; }
// 링크를 추출하여 표시 data( "a" ).each(function( idx ) {
var text = data( this ).text( ); var hrefOne = data( this ).attr( "href" );
if( !hrefOne ) { return; }
// 상대경로를 절대 경로로 변환 var hrefTwo = urlType.resolve( url, hrefOne );
// 결과를 표시 console.log( text + " : " + hrefOne ); console.log( " => " + hrefTwo + "\n" ); }); }); |
'Node.js' 카테고리의 다른 글
[Node.js] Serial Port를 이용한 Arduino 이벤트 실행 (0) | 2019.06.13 |
---|---|
[Node.js] Terminal 명령을 수행하는 node_cmd 모듈 (0) | 2019.05.10 |
[Node.js] node.js로 PDF 문서 생성하기 (2) | 2019.04.11 |
[Node.js] package.json과 npm i 명령 (0) | 2019.04.02 |
[Node.js] Node.js 채팅방 제작 (0) | 2019.02.12 |