ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Headless Browser, Puppeteer
    Tech/Development 2020. 7. 22. 23:24

    Puppeteer! 그림과 이름만 봐도 대충 무엇인지 알 수 있을 것 같다. Puppeteer은 Chrome/Chromium 브라우저를 제어하도록 도와주는 Node.js 라이브러리이다. 구글에서 제공하는 공식 문서를 보면, 다음과 같은 목적으로 사용될 수 있음을 보여준다.

     

    1. 웹 페이지 화면을 스크린샷이나 PDF로 생성할 수 있다. 

    2. SPA(Single Page Application & Client-Side Redering) / SSR(Server-Sied Rendering) 페이지를 크롤링할 수 있다.

    3. 폼 입력, UI 테스트, 키보드 입력 등과 같은 기능을 자동화시킬 수 있다.

    4. 더 나아가서, 웹 페이지(서비스)를 자동으로 테스트하는 도구를 만들 수 있다.

    5. 웹 페이지의 Timeline Trace 기록하여 성능 관련 이슈를 진단할 수 있다.

    6. Chrome Extensions를 테스트할 수 있다.

    [출처 : Google Puppeteer 공식문서]

     

    위와 같은 기능을 한다. 비슷한 라이브러리로는 Python의 Selenium이 있다. 많이들 접해봤을 것이다. Selenium도 따로 Headless 속성을 부여하여 백그라운드에서 작동할 수 있게 만들 수는 있다. 이 외에도 PhantomJS도 있긴 하다. 사실, Selenium으로도 Headless가 가능한지 지금 처음 알았다.... 이전에 Selenium을 사용하면서 느려서 짜증날 때가 많았는데, headless 속성 부여 및 gpu 사용 안하는 속성을 부여하고나니 속도가 굉장히 빨라졌다. 다음에 Selenium을 쓸 때는 꼭 기억해야겠다.😅

    # selenium headless 및 gpu 사용 안 함 옵션 부여
    
    from selenium import webdriver
    
    driver = webdriver.ChromeOptions()
    
    driver.add_argument('headless')
    driver.add_argument('disable-gpu')

     

    나는 주로 Javascript를 사용하기도 했고, Python 보다는 JS가 편했기 때문에 Puppeteer로 오게 되었다. 사용하면서 느낀 점은, 개인적으로 Puppeteer가 더 직관적이고 이것저것 합쳐서 사용하기 편한 것 같다.

     

    설치부터 몇 가지 사용법에 대해 알아보도록 하자.

     

    0. Puppeteer 설치하기


    별 거 없다. 그냥 일반 라이브러리 설치하듯 설치하면 된다. puppeteer 외에 puppeteer-core라는 라이브러리가 존재하는 것을 확인할 수 있는데, puppeteer-core는 크로미움을 함께 설치하지 않고, 모든 PUPPETEER_* 환경변수를 무시한다고 한다. 대부분의 경우, puppeteer을 사용하니, puppeteer을 사용하도록 하자(puppeteer VS puppeteer-core)

    npm install puppeteer
    
    # or use puppeteer-core
    npm install puppeteer-core

     

    1. Puppeteer 실행하기


    const puppeteer = require('puppeteer');
    
    
    (async function x() {
        const browser = await puppeteer.launch();
        
        const page = await browser.newPage();
        
        await page.goto('https://example.com');
        await page.screenshot({path: 'example.png'});
        await browser.close();
        
    }())

    Puppeteer을 사용할 때, 주의할 점은 async/await 구문을 사용해 동기식으로 만들어 사용해야한다는 것이다. 브라우저를 열고, 어떠한 작업을 해 나가는 것은 순차적으로 행해져야 되기 때문이다.

     

    위의 코드는 Puppeteer을 사용해 스크린샷을 찍어보는 것인데, 해당 코드를 실행하고 나면 같은 경로에 사진 하나가 생성되어 있을 것이다. 간혹 이게 정말 작동되는 것인가? 궁금할 때도 있을 텐데, 그럴 때는 옵션 값을 다르게 주어 아래처럼 Headless를 풀어주면 된다.

    // Puppeteer Launch Options
    // 그 외의 다양한 옵션들, https://devdocs.io/puppeteer/index#puppeteerlaunchoptions
    
    const browser = await puppeteer.launch({
    	headless:false,
    });

     

    당황스럽게도, 아래와 같은 에러가 나오는 경우도 있다. puppeteer 설치 시 같이 설치된 브라우저의 버전이 달라서 나오는 에러인데, 이러한 경우에는 직접 chromium을 다운로드 받고 puppeteer launch option에 executablePath에다 경로 설정을 해 주면 된다.

    (node:4266) UnhandledPromiseRejectionWarning: Error: Could not find browser revision 768783. Run "PUPPETEER_PRODUCT=firefox npm install" or "PUPPETEER_PRODUCT=firefox yarn install" to download a supported Firefox browser binary.
    at ChromeLauncher.launch (webpack:///./node_modules/puppeteer/lib/cjs/puppeteer/node/Launcher.js?:86:23)
    at async eval (webpack:///./src/server.js?:23:21)​

    경로 설정을 하면 다음과 같다. Mac과 Windows에서 사용하는 크로미움은 다르므로, 주의하도록 하자.

    const browser = await puppeteer.launch({
    	executablePath: '/path/to/Chrome'
    });
    
    // mac os
    executablePath : '/Chromium.app/Contents/MacOS/Chromium';
    
    // windows
    executablePath : 'chrome-win\\chrome.exe';

     

    2. Puppeteer의 다양한 기능


    const page = await browser.newPage();
    await page.goto('https://example.com');
    
    // document 접근
    const data = await page.evaluate( () => {
    	let el = document.querySelector('')
        return el
    })
    
    // document 접근 시, 인자 할당해 사용
    // https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageevaluatepagefunction-args
    const data = await page.evaluate( (value) => {
    	console.log(value)
    }, value)

    몇 가지 기능만 살펴보긴 했지만, 이 외에도 웹 페이지의 헤더/세션/쿠키 등을 살펴볼 수도 있고, 폼 태그에 직접 값을 입력할 수도 있다. 이 외에도 정말 무궁무진한 기능들이 있어. 사용하기 나름인 것 같다. 앞으로 자동화 서비스를 만들 때 유용하게 쓸 수 있을 것 같다.

    'Tech > Development' 카테고리의 다른 글

    Golang #2 - Method vs Function  (0) 2021.03.01
    Golang #1 - Map  (0) 2021.02.14
    Golang Reserved Words  (0) 2021.02.11
    Node with Python(python-shell)  (0) 2020.07.22
    카카오톡 챗봇 만들기 - 1  (3) 2020.04.11

    댓글 0

Designed by Tistory.