Node.js

puppeteer

blackbearwow 2024. 8. 17. 09:53

puppeteer는 페이지에 js코드를 실행시키는 등 selenium과 다르게 자유도가 굉장히 높다.

 

하지만 24.08.21기준 puppeteer-extra-plugin-stealth가 1년째 업데이트 되지 않고있다.

cloudflare를 우회하고싶다면 puppeteer-real-browser를 사용하자.


설치

npm install puppeteer

import

const puppeteer = require('puppeteer');

 

1. 브라우저 시작

const browser = await puppeteer.launch();
const page = await browser.newPage();

puppeteer는 기본적으로 ui가 없는 headless상태로 실행된다.

ui를 보길 원한다면 launch에 headless:false를 옵션으로 준다.

defaultViewport를 null로 해야 창 크기에 맞게 viewport가 변한다. 기본적으로 '{width: 800, height: 600}'이다.

const browser = await puppeteer.launch({headless:false, defaultViewport:null});

페이지마다 cookie와 local storage가 공유되지 않길 원한다면 browser context를 사용할 수 있다.

const browser = await puppeteer.launch();

const context = await browser.createBrowserContext();

const page1 = await context.newPage();
const page2 = await context.newPage();

await context.close();

 

2. 브라우저 종료

await browser.close();

3. page class

창 크기 설정

await page.setViewport({ width: 1080, height: 1024 });

페이지 이동

await page.goto('https://www.naver.com/');

앞으로 가기, 뒤로가기, 새로고침

await page.goForward();
await page.goBack();
await page.reload();

title 얻기

let title = await page.title();

url 얻기

let url = page.url();

전체 html얻기

let fullHTML = await page.content();

쿠키값들 얻기

let cookies = await page.cookies();

쿠키 만들기, 쿠키 제거하기

await page.addCookie();
await page.deleteCookie();

pdf 생성하기

await page.pdf({path:'pdf.pdf', format: 'A4'});

스크린샷 찍기

await page.screenshot({path:'screenshot.png',type:'png', fullPage:true})

동영상 찍기

const recorder = await page.screencast({path:'screencast.webm'});
// 단순히 기다리는 것이 아닌 클릭등 무언가를 한다.
await recorder.stop();

title 기다리기

await page.waitForFrame(async frame => {
	return (await frame.title()).includes('네이버 검색');
})

navigation 완료 기다리기

await page.waitForNavigation();

network 작업 모두 기다리기

await page.waitForNetworkIdle();

기다리지 않고 query하기

page.$()
page.$$()
page.$eval()
page.$$eval()

page.$()와 page.$$()는 select 결과를 Element로 하나, 배열로 반환한다.

page.$eval()와 page.$$eval()는 select 결과를 callback의 인자로 넘긴다.

javascript 실행하기

const aHandle = await page.evaluate('1 + 2');
const aHandle = await page.evaluate(() => 2);
await page.evaluate(()=>{
	return new Promise((resolve)=>{
		setTimeout(()=>resolve(), 2000);
	});
});

 

4. locator class

locator는 객체를 찾고 그것들에게 동작을 취한다. 객체가 동작할 준비가 되지 않아 동작이 실패하면, 재시도한다.

 

클릭하기

await page.locator('button').click();

locator는 자동으로 다음을 체크한다.

- 요소가 보임창 안에 있는 것

- 요소가 visible 또는 hidden이 될때까지 기다리는 것

- 요소가 enable될때까지 기다리는 것

- 요소가 두개의 애니메이션 프레임을 거쳐 안정적인 경계 상자를 가질 때까지 기다리는 것

 

input에 값 넣기

await page.locator('input').fill('value');

 

요소 hover하기

await page.locator('div').hover();

 

요소 scroll하기

await page.locator('div').scroll({
  scrollLeft: 10,
  scrollTop: 20,
});

 

요소 보이기까지 기다리기

await page.locator('.loading').wait();

 

함수로 기다리기

selector로 기다리는게 아니라 함수로 상태를 지정해줘서 기다리는 방법이다.

await page
  .locator(() => {
    let resolve!: (node: HTMLCanvasElement) => void;
    const promise = new Promise(res => {
      return (resolve = res);
    });
    const observer = new MutationObserver(records => {
      for (const record of records) {
        if (record.target instanceof HTMLCanvasElement) {
          resolve(record.target);
        }
      }
    });
    observer.observe(document);
    return promise;
  })
  .wait();

 

locator 설정

locator의 기다리는 조건을 설정할 수 있다.

await page
  .locator('button')
  .setEnsureElementIsInTheViewport(false)
  .setVisibility(null)
  .setWaitForEnabled(false)
  .setWaitForStableBoundingBox(false)
  .click();

 


참고: https://pptr.dev/category/introduction

-