puppeteer
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
-