[Puppeteer] Puppeteer와 Cheerio를 활용한 데이터 스크랩핑[Puppeteer] Puppeteer와 Cheerio를 활용한 데이터 스크랩핑

Posted at 2019. 6. 20. 21:10 | Posted in Node.js/Puppeteer




■ 퍼펫티어를 이용한 유튜브 채널 스크랩핑




유튜브 API가 제대로 동작하지 않게 되었다.


cheerio-httpcli 모듈로 YouTube 페이지의 데이터를 스크래핑 하려 해보았지만.


유튜브의 경우 cheerio-httpcli를 통한 단순한 데이터 스크랩핑을 해보니


많은 수의 json형태의 데이터를 가져오기에


포기하던 차에 puppeteer를 활용해 보기로 했고


결과는 어느정도 만족할 수 있는 수준이었다.






위와 같이 유튜브 특정 채널의 업로드 영상을 가져와 보려고 한다.




# 소스코드

 puppeteer_ra_om_musiq.js

const puppeteer = require( "puppeteer" );

const cheerio = require( "cheerio" );


puppeteer.launch( { headless : true } ).then(async browser => {


const page = await browser.newPage();

await page.goto( "https://www.youtube.com/user/RaOmMusiq/videos/", { waitUntil : "networkidle2" } );

        // YouTube 페이지의 <ytd-grid-renderer> 태그 안의 내용을 가져온다.

const html = await page.$eval( "ytd-grid-renderer", e => e.outerHTML );


        // console.log(html);


const datacheerio.loadhtml );

data( "a.ytd-grid-video-renderer" ).each( function( key, val ) {


               // substring을 사용하여 불필요한 값을 잘라낸다. 

var videoId = data( val ).attr( "href" ).substring( 9, 20 );

var videoTitle = data( val ).text();

console.log( "VIDEO ID = ", videoId );

console.log( "VIDEO TITLE = ", videoTitle );

});

});





# 출력결과




위와같이 필요로 하는 YouTube 영상의 아이디 값 타이틀 제목을 얻어오는 모습을 확인 할 수 있다.






Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Puppeteer] 퍼펫티어를 이용한 CRAWLING 작업[Puppeteer] 퍼펫티어를 이용한 CRAWLING 작업

Posted at 2019. 4. 26. 16:27 | Posted in Node.js/Puppeteer





■ 퍼펫티어를 이용한 크롤링 작업





필자가 노드를 처음 접하게된 이유는 급작스러운 크롤링 작업 때문이었다.


당시에는 PhantomJSCasperJS를 통해 작업을 진행 하였고,


왠만학 작업은 위 두개를 가지고 어떻게든 진행 할 수 있었지만.


점점 작업해야하는 프로젝트가 고도화 됨에 따라,


다른 Node.js와의 라이브러리 범용이 어려운 CasperJS의 한계를 느끼게 되었고


Puppeteer를 주로 사용하게 되었다.


Node.js를 통한 크롤링 작업을 준비중인 사람이라면,


그만 퍼펫티어를 더 활용하는것이 스트레스를 덜 받을 것이라고 생각한다.




# 소스 코드

 puppeteer_login.js

const puppeteer = require("puppeteer");


// 사용시 인위적인 딜레이를 주기위한 함수

function delay( timeout ) {

  return new Promise(( resolve ) => {

    setTimeout( resolve, timeout );

  });

}


puppeteer.launch({

  headless : false // 헤드리스모드의 사용여부를 묻는다.

, devtools : true // 개발자 모드의 사용여부를 묻는다.

}).then(async browser => {


const page = await browser.newPage();

// 로그인할 티스토리 블로그의 관리자 페이지를 지정

await page.goto( "http://magic.wickedmiso.com/manage/", { waitUntil : "networkidle2" } );

// 티스토리의 아이디와 암호를 입력한다.

await page.type( "div.box_login > div.inp_text:nth-child(1) > input#loginId", "티스토리 아이디" );

await page.type( "div.box_login > div.inp_text:nth-child(2) > input#loginPw", "티스토리 패스워드" );



/* document.getElementByI로 직접 입력할 input BOX를 선택하여 작업하는 것도 가능하다.

await page.evaluate(() => {

document.getElementById( "div.box_login > div.inp_text:nth-child(1) > input#loginId" ).value = "티스토리 아이디";

                document.getElementById( "div.box_login > div.inp_text:nth-child(2) > input#loginPw" ).value = "티스토리 패스워드";

});

*/


await delay(3000);

        // 로그인 SUBMIT 기능

const elementHandle = await page.waitFor( "input" );

await elementHandle.press( "Enter" );

await delay(5000);

        /* 로그인이후 방문 기록 데이터를 콘솔에 띄워본다. */

const emToDay = await page.waitFor( "div.box_blog > dl.count_visitor:nth-child(1) > dd" );

        const txtToDay = await page.evaluate( emToDay => emToDay.textContent, emToDay );

        console.log("-. 오늘 방문자 수", txtToDay);

    

const emYesterDay = await page.waitFor( "div.box_blog > dl.count_visitor:nth-child(2) > dd" );

        const txtYesterDay = await page.evaluate( emYesterDay => emYesterDay.textContent, emYesterDay );

        console.log("-. 어제 방문자 수", txtYesterDay);


const emCumulativ = await page.waitFor( "div.box_blog > dl.count_visitor:nth-child(3) > dd" );

        const txtCumulativ = await page.evaluateemCumulativ => emCumulativ.textContentemCumulativ );

        console.log("-. 누적 방문자 수", txtCumulativ);

});





# 노드 실행

 C:> node puppeteer_login.js





# 출력 결과











Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기

[Puppeteer] 퍼펫티어 설치 및 설정하기[Puppeteer] 퍼펫티어 설치 및 설정하기

Posted at 2019. 4. 23. 11:00 | Posted in Node.js/Puppeteer




GitHub : https://github.com/GoogleChrome/puppeteer

GitHub(API) : https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md

참고 : https://blog.outsider.ne.kr/1318

참고 : https://www.samsungsds.com/global/ko/support/insights/090717_RD_GitPuppeteer.html

API : https://pptr.dev/

NPM : https://www.npmjs.com/package/puppeteer

포스트 : SW개발자의 메카 깃허브와 주목받는 깃허브(GitHub) 트렌드 퍼펫티어(Puppeteer)






■ 헤드리스(Headless)란?





#01. 헤드리스란?



헤드리스 브라우저란 응용프로그램으로서 존재하는 파이어 폭스, 크롬, 익스플러, 사파리와 같이 실제로 존재하는 브라우저를 지칭하는 것이 아니라,


일반적인 CLI환경에서 브라우저가 사용자의 눈에 보여지지 않고, 백그라운드에서 작동하는 것을 말한다.


그러므로 헤드리스 브라우저라는 표현보단, 헤드리스 모드라고 하는것이 더 정확한 표현이라고 보아야 할것이다.





#02. 헤드리스 모드를 지원하는 브라우저



크롬(헤드리스 크롬), 파이어 폭스등은 헤드리스 모드를 지원하며


가장 널리 알려진 팬텀JS(Wabkit)등 아예 헤드리스 모드만을 위해 제작된 제품들도 존재한다.





#03. 헤드리스를 사용하는 이유



헤드리스 모드의 사용은 주로 자동화 목적을 가진다.







■ 퍼펫티어(Puppeteer)란?



퍼펫티어(Puppeteer)는 Headless Chrome을 쉽게 사용할 수 있도록 Google Chrome 팀에서 공개한 Node.js 라이브러리이다.

(퍼펫티어는 구글의 크롬(Chrome)에 헤드리스를 추가했다.)


퍼펫티어는 구글 크롬의 헤드리스 모드를 사용(크로미움 기반의 브라우저)하여 브라우저를 사용자에게 보여주지 않고, 백그라운드에서 작동할 수 있게 해준다.







■ 퍼펫티어 설치하기



 $ npm install puppeteer







■ Node.js로 퍼펫티어 실행하기




# 소스코드

 puppeteer_start.js

const puppeteer = require("puppeteer");


// puppeteer.executablePath()는 설치한 puppeteer 노드모듈의 번들로 제공되는 chromium 브라우저의 경로의 주소값을 가진다.

// 해당 예제는 puppeteer.launch를 통해 퍼펫티어를 실행할때 해당 경로의 값을 지정한다.

console.log(puppeteer.executablePath());



// 딜레이를 주기 위한 함수

function delay( timeout ) {

  return new Promise(( resolve ) => {

    setTimeoutresolvetimeout );

  });

}



puppeteer.launch({

         headless : false // 헤드리스모드의 사용여부를 묻는다

, devtools : false // 브라우저의 개발자 모드의 오픈 여부를 묻는다

, executablePathpuppeteer.executablePath() // 실행할 chromium 기반의 브라우저의 실행 경로를 지정한다.

, ignoreDefaultArgs : false // 배열이 주어진 경우 지정된 기본 인수를 필터링한다.(중요 : true사용금지)

, timeout : 30000 // 브라우저 인스턴스가 시작될 때까지 대기하는 시간(밀리 초)

, defaultViewport : { width : 800, height : 600 } // 실행될 브라우저의 화면 크기를 지정한다.

, args : [ "about:blank" ]

}).then(async browser => {

const page = await browser.newPage();

// 새탭을 열고 작업을 수행할 페이지를 지정한다.

await page.goto( "http://magic.wickedmiso.com/", { waitUntil : "networkidle2" } );

// 5초간딜레이를 준다.

await delay(5000);

// 스크린샷을 찍는다.

await page.screenshot( { path : "wickedBlog.png" } );

// 모든 작업을 수행하면 브라우저를 닫고 퍼펫티어를 종료한다.

await browser.close();

});





#01. puppeteer.launch 실행 옵션



puppeteer.launch( [ 옵션 ] )을 사용하여 퍼펫티어를 실행하여 브라우저를 제어어할 수 있다.



옵 션

기 본 값

설     명

 ignoreHTTPSErrors

false

 · 탐색중에 HTTPS 오류를 무시할것인지를 묻는다.

 headless

true

 · 번들로 제공되는 크로미움 브라우저를 실행할 것인지를 묻는다.

 · false로 실행을 하게되면 크로미움 브라우저가 보여지고 실행과정을 화면에서 확인 할 수 있다.

 devtools

false

 · 각 탭에 대해 개발자도구를 자동으로 열지 여부를 묻는다.

 · 사용할경우 headless : false로 설정해 주어야 한다.

 executablePath

Chromium

Broswer

 · 번들로 제공되는 크로미움이 아닌 다른 브라우저의 사용시 설정한다.

 · 사용할 실행 파일을 설정하면 설정한 크로미움 기반 여러 브라우저의 사용이 가능하다.

   (Chrome, Opera, Whale, Vivaldi, Brave 등)

 · 참고 : 작성중

 slowMo

0

 · 지정된 시간(ms : 밀리 초) 까지 퍼펫티어의 작업을 느리게 실행한다.

 · 무슨 일이 일어나고 있는지 확인 할 때 유용하다.

 defaultViewport

800 x 600

 · 각 페이지에 대해 일괄된 화면SIZE를 지정한다.

 · null을 지정하면 비활성화 된다.

 · 속성

  -. width : 페이지 너비(픽셀)

  -. height : 페이 높이(픽셀)

  -. deviceScaleFactor : 장치 배율 인수를 지정한다(dpr로 생각할 수 있음). (기본값 : 1)

  -. isMobile : meta viewport 태그가 고려되는지 여부를 묻는다.(기본값 : false)

  -. hasTouch : 터치 이벤트를 지원하는지 여부를 묻는다. (기본값 : false)

  -. isLandscape : 가로 모드인지 여부를 묻는다. (기본값 : false)

 ignoreDefaultArgs

false 

 · 배열이 주어진 경우 지정된 인수를 필터링 한다.

 · 특별한 상황이 아닌이상 변경하지 말고 false 기본값을 사용하자(true 변경 금지)

 handleSIGINT

true

 · 브라우저에서 Ctrl + C 버튼을 클릭하여 프로세스를 종료시킬 수 있다.

 handleSIGTERM

true

 · 실행한 터미널에서 Ctrl + C 버튼을 클릭하여 프로세스를 종료시킬 수 있다.

 handleSIGHUP

true

 · 실행한 터미널에서 Ctrl + C 버튼을 클릭하여 프로세스를 종료시킬 수 있다.

 timeout

30000

 · 브라우저 인스턴스가 시작될 때까지 대기하는 최대 시간(ms : 밀리 초)를 지정한다.

 · 0을 지정하여 시간 제한을 해제 할 수 있다.

 dumpio

false

 · 브라우저 프로세스의 로그를 stdout 및 stderr을 process.stdout 및 process.stderr

   (구글 번역 내용을 적었다. 프로세스의 실행 로그 관리로 추정되는데, 좀더 확인이 필요할듯)

 userDataDir

-

 · 사용자 디렉토리의 경로를 지정한다.

 · 경로를 지정하면 크롬 브라우저의 사용자 접속정보를 그대로 가지고 퍼펫티어가 실행되므로

  로그인등의 인증절차가 필요한 경우 유용하게 사용할 수 있다.

 · 참고 : https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md

 env

process.env

 · 브라우저에서 볼 수 있는 환경 변수를 지정 

 pipe

false

 · 웹 소켓대신 파이프를 통해 브라우저에 연결한다.

  (구글 번역 내용을 적었다. 프로세스의 실행 로그 관리로 추정되는데, 좀더 확인이 필요할듯)

 args

-

 · 브라우저 인스턴스에 전달할 추가 인수의 목록

 · 크롬 플래그 목록 참고 : https://peter.sh/experiments/chromium-command-line-switches/






#02. page.goto 이벤트 waitUntil 속성



※ waitUntil : 페이지를 호출하고 작업을 진행할 시점을 결정한다.


옵 션

설   명

 load

 · load 이벤트가 시작되면 탐색이 완료되는 것으로 간주한다.

 docntentload

 · HTML 문서가 완전히 로드 및 파싱되었을 경우(DOMContentLoaded 이벤트) 탐색이 완료되는 것으로 간주한다.

 networkidle0

 · 최소한 500ms 동안 네트워크 연결이 0개 이상 없을때 탐색이 완료되는 것으로 간주한다. 

 networkidle2

 · 최소한 500ms 동안 두 개 이상의 네트워 연결이 없을 때 탐색이 완료되는 것으로 간주한다.





# 출력결과① - 브라우저





# 출력결과② - 스크린샷 이미지 파일








Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기