본문 바로가기
[IT] Node.JS/[웹크롤링] Puppeteer

[Node.js] Headless 브라우저 웹 크롤링 Puppeteer 소개, 설치 및 샘플 예제

by 오리엔탈킴 2022. 1. 7.

 

안녕하세요, 오리엔탈 킴입니다.

 

Headless Browser를 이용한 웹 크롤링(Crawling) 및 웹 스크래핑(Scraping) 툴인 Puppeteer에 대해 간단히 알아보고, 초기 설치 및 세팅 후 간단한 샘플 예제를 구현하도록 하겠습니다. 이 글을 시작으로 추후 Puppeteer를 이용하여, 여러 웹크롤링 예제와 웹 자동화 테스트 툴 (Web UI Testing)을 구현하는 글도 올리도록 하겠습니다.

 

Puppeteer란, 크롬 DevTools 프로토콜을 이용하여 Chrome 및 Chromium을 자유롭게 컨트롤할 수 있게 해주는 웹크롤링 Node.js 라이브러리입니다. (Chromium은 오픈소스 코어 웹 브라우저로 크롬 등 다양한 브라우저들이 Chromium을 기초해서 개발되었습니다.)

 

Puppeteer(퍼펫 티어)는 Selenium 같은 다른 툴과는 다르게 기본적으로 Headless 브라우저에서 동작을 하는데, Headless 브라우저는 사용자에게 보이는 디스플레이 및 UI 기능을 제거하고 백 단에서 동작하는 브라우저로 더 적은 리소스로 더 빠르게 동작할 수 있게 해 줍니다. (물론 일반 브라우저에서도 동작이 가능합니다.)

 

Puppeteer는 Google 크롬팀에서 개발되었고, 사용자가 하는 크롬의 거의 모든 기능을 코드로 구현이 가능하게 하여 웹크롤링 및 UI/UX 자동화 테스트 등을 가능하게 해 줍니다. 단 Chrome 및 Chromium을 제외한 다른 브라우저에서는 동작이 불가능합니다.

 

1. Puppeteer 설치

먼저 Node.js 및 VS Code가 세팅이 되어 있어야 합니다.

2021.12.23 - [[IT] Node.JS] - [Node.js 개발환경] Node.js 및 VS code 설치, Node.js 초기 프로젝트 생성 및 실행

위 글을 참고하여, VS Code 내 puppeteerPjt라는 폴더를 생성하고, npm init 및 launch.json 파일을 생성합니다.

VS Code 하단의 터미널 창에서 아래와 같이 명령어를 쳐서 puppeteer-core 라이브러리를 설치합니다.

(VS Code 터미널창 실행은 [Ctrl + `] 단축키 또는 상단 메뉴 [View > Terminal]입니다.)

 

npm i puppeteer-core

 

puppeteer 설치 명령어 입력 화면
install puppeteer

 

npm i puppeteer와 puppeteer-core로 설치가 가능한데, puppeteer는 Chrominum 브라우저가 같이 설치가 되고 puppeteer-core는 브라우저가 따로 설치가 되지 않기 때문에 기존에 설치한 Chrome이나 Chrominum으로 동작을 해야 합니다. 이미 크롬이 설치되어 있다면 굳이 중복으로 설치할 필요가 없기 때문에 위와 같이 puppeteer-core를 설치합니다.

 

2. Puppeteer 샘플 예제 - 스크린샷

Puppeteer는 브라우저에서 할 수 있는 수많은 기능들을 여러 API로 제공을 하고 있는데요, 해당 내용은 공식 페이지인 https://pptr.dev/에서 (영어이긴 하지만..) 상세히 확인하실 수 있습니다.

 

https://pptr.dev/

 

pptr.dev

 

공식 페이지에 나와 있는 예제 중 스크린샷 예제를 먼저 구현해 보겠습니다. 아주 간단한 예제인데, 아래의 코드를 index.js 파일에 작성해 줍니다. puppeteer는 동기식으로 작성을 하게 되면 꼬이는 케이스가 많기 때문에 아래와 같이 비동기식으로 async/await를 이용하여 작성해줍니다.

간단하게 puppeteer는 launch를 통해 브라우저를 정의하고 newPage를 통해 신규 페이지를 오픈하고, goto 명령을 통해 페이지로 이동을 해서 screenshot 명령을 통해 스크린샷을 저장하는 식으로 실제 사람이 수행하는 것처럼 동작을 합니다. launch를 할 때 여러 옵션을 정의할 수 있는 아래 사용된 옵션은 아래와 같습니다.

  •  executablePath : puppeteer-core를 설치를 하였다면, 설치되어있는 크롬(혹은 Chromium)의 경로를 정의해야 합니다. (Window의 경우 경로를 '\'가 아닌 '/'로 사용함을 주의)
  •  defaultViewport : 브라우저의 디폴트 해상도는 800 × 600px라서, 가장 흔하게 사용하는 1920X1080 px 해상도로 변경하였습니다.
  • headless : 백 단에서 돌아가게 할지 말지를 선택하는 옵션으로 디폴트는 true인데, 개발 중 실제 돌아가는 것을 확인하고 싶다면 false로 정의하면 됩니다.

 

const puppeteer = require('puppeteer-core');

(async () => { 
  const browser = await puppeteer.launch({ // Puppeteer용 브라우저 실행
    executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' 
    ,defaultViewport : {
      width: 1920,
      height: 1080
    }
    //,headless : false
    });

  const page = await browser.newPage(); // 신규 탭(페이지) 생성

  await page.goto('https://kim-oriental.tistory.com'); // 해당 URL로 이동
  await page.screenshot({ path: 'screenshot.png' }); // 해당 경로에 스크린 샷 저장

  await browser.close(); // 브라우저 종료
})();

 

VS Code에서 lauch.json이 세팅이 되었다면 F5 버튼, 아니라면 터미널에서 node index.js를 입력하여 실행을 시키면 아래와 같이 동일 폴더에 screenshot.png 파일이 생성되면서 스크린샷 이미지가 저장된 것을 확인할 수 있습니다. 유사하게 pdf 명령을 통해 pdf 파일로도 저장할 수 있습니다. (해당 예제는 공식 페이지 https://pptr.dev/ 에서 확인 가능합니다)

 

스크린샷 예제 결과 화면
스크린샷 예제 결과

 

3. Puppeteer 샘플 예제 - 버튼 클릭

다음 샘플 예제는 간단하게 웹 페이지에서 버튼을 클릭해서 변경된 페이지를 스크린샷을 찍는 예제를 구현해보도록 하겠습니다. 이 블로그의 메인 페이지 (https://kim-oriental.tistory.com/) 우측 상단에 글 리스트를 어떻게 보여줄지 선택하는 버튼이 있는데, 처음에는 줄 모양의 리스트형으로 되어 있는데 Puppeteer로 그 옆에 네모 모양의 썸네일형을 클릭을 하도록 하겠습니다. 

 

클릭할 버튼 화면
블로그 상단 버튼

 

먼저 해당 버튼 태그의 Class 혹은 ID를 알아야 하는데요, 크롬에서 F12를 눌러서 DevTools를 실행하여 상단 Select Element 버튼을 클릭하여 해당 버튼의 Class 이름이나 ID를 확인합니다. 아래와 같이 해당 버튼의 id는 미정의 이고 class가 "thum"으로 되어 있습니다. id(#)는 유일 값이지만 class(.)는 중복 값이 올 수가 있는데, DevTools에서 검색을 해보면 해당 페이지에 thum이라는 class는 여러 개가 존재합니다. 그래서 상위 계층까지 확인을 하면 해당 영역의 class가 "list-type"인 것을 알 수 있습니다. class를 의미하는 "."을 붙여서 ".list-type .thum"이라는 영역은 페이지 내에 유일 값임을 확인할 수 있습니다.

 

DevTools를 통해 클릭 대상 정보 확인
DevTools를 통해 클릭할 대상 확인

 

위에서 작성한 스크린샷 예제 중간에 아래와 같이 click 매소드를 추가해줍니다. (페이지가 지연되어 제대로 동작을 안 할 경우를 대비하여 waitForSelector 매소드도 앞뒤로 추가하였습니다)

 

const puppeteer = require('puppeteer-core');

(async () => { 
  const browser = await puppeteer.launch({ 
    executablePath: 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe' 
    ,defaultViewport : {
      width: 1920,
      height: 1080
    }
    //,headless : false
    });

  const page = await browser.newPage(); 

  await page.goto('https://kim-oriental.tistory.com');
  
/*                       추가된 코드                       */
  await page.waitForSelector('.list-type .thum'); // 클릭할 버튼이 로드 될 때까지 Wait
  await page.click('.list-type .thum'); // 썸네일 버튼 클릭
  
  await page.waitForSelector('.inner'); // 글 리스트 영역이 로드 될 때까지 Wait
  /*                     추가된 코드                       */
  
  await page.screenshot({ path: 'screenshot2.png' });

  await browser.close();
})();

 

해당 코드를 Run 하면 아래와 같이 썸네일 버튼을 클릭한 결과가 캡처되어, 위의 첫 번째 샘플 결과와는 다른 모습의 결과를 확인할 수 있습니다. 

 

썸네일 버튼 클릭 후 화면 캡처 결과
썸네일 버튼 클릭 후 화면 캡처

 

간단하게 Puppeteer 설치 및 이를 이용한 웹클로링 샘플 예제를 구현해봤습니다. 추후에 더 복잡한 웹 크롤링 예제 및 웹 테스팅 자동화 툴을 Puppeteer를 이용하여 구현하는 글을 작성해보도록 하겠습니다. 

 

반응형

댓글