Node Puppeteer crawling

원장·2024년 12월 17일

라이브러리 분석

목록 보기
1/2

Puppeteer

이번에 좋은 기회로 어떤 교육을 받게되었습니다.

거기서 잘하는 개발자는 라이브러리 내부 구현을 분석/파악해서 문제를 해결하는 능력을 갖춰야한다고합니다.

하지만 저는 지금까지 개발하면서 어떤 특정 라이브러리를 분석/파악하겠다는 생각조차 해본 적이 없어서 스스로에게 실망스러웠습니다.

해당 교육에 감사하며, 오늘부터 해보려고합니다!!! 가즈앗!!!!!

Puppeteer란 무엇인가?

Puppeteer는 Headless Chrome을 제어하기 위한 Node.js 라이브러리입니다.

자동화된 브라우저 작업, 웹 스크래핑, UI 테스트, 화면 캡쳐 등에 쓰입니다.

Headless Chrome이란?

사용자 인터페이스(UI) 없이 실행되는 Chrome 브라우저입니다.
백그라운드에서 실행되며, UI 렌더링이 없어서 일반 Chrome보다 성능과 리소스 소모가 가볍습니다.
Puppeteer나 Selenium과 같은 라이브러리를 사용하여 브라우저를 제어할 수 있습니다.

Puppeteer 설치 및 기본 설정

1.node와 npm을 설치합니다.

2.puppeteer를 설치합니다.

npm install puppeteer

3.기본예제(화면캡쳐)

const puppeteer = require('puppeteer');

(async () => {
  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의 주요 기능 및 사용법

페이지 조작

페이지 열기 및 닫기: browser.newPage(), page.close()
URL 이동: page.goto()
콘솔 출력 및 로그 확인: page.on('console')
페이지 HTML 가져오기: page.content()
뷰포트 설정: page.setViewport()

요소 선택 및 조작

요소 찾기: page.$() 및 page.$$()
텍스트 입력: page.type()
버튼 클릭: page.click()
드롭다운 선택: page.select()
스크롤 및 페이지 이동: page.evaluate() 활용.

네트워크 요청/응답 처리

요청/응답 가로채기: page.setRequestInterception()
API 호출 모니터링: page.on('request')
이미지 및 리소스 차단: 네트워크 필터링 설정.

화면 캡쳐 및 PDF 생성

스크린샷 저장: page.screenshot()
특정 영역 캡처: bounding box를 활용한 부분 캡처.
PDF 생성: page.pdf()

브라우저 이벤트

browser.on('disconnected') 및 page.on('load')
다중 탭 제어: browser.pages()를 활용한 탭 관리.

고급 활용법

헤드리스 모드와 헤드 모드

기본적으로 헤드리스 모드!

헤드 모드 활성화 원할 때는

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

Puppeteer와 Chrome DevTools Protocol (CDP)

Puppeteer는 Chrome DevTools Protocol을 기반으로 작동합니다.

여기서 CDP란 브라우저를 프로그래밍적으로 제어할 수 있도록 지원하는 프로토콜입니다.

CDP를 활용하면 Chrome의 개발자 도구에서 가능한 거의 모든 작업(디버깅, 성능 모니터링, 페이지 조작 등)을 코드로 자동화할 수 있습니다.

1.Headless Chrome 실행 시 CDP 활성화

chrome --headless --remote-debugging-port=9222

2.webSocket을 통해 CDP에 연결

WebSocket 라이브러리를 사용해 CDP와 직접 통신합니다.

const WebSocket = require('ws');
const fetch = require('node-fetch');

// Chrome Debugging Protocol 엔드포인트 찾기
(async () => {
  const response = await fetch('http://localhost:9222/json'); // CDP 엔드포인트
  const tabs = await response.json();

  const webSocketDebuggerUrl = tabs[0].webSocketDebuggerUrl;
  const ws = new WebSocket(webSocketDebuggerUrl);

  ws.on('open', () => {
    console.log('CDP 연결 성공!');

    // CDP 명령 전송: 새 페이지로 이동
    const command = {
      id: 1,
      method: 'Page.navigate',
      params: { url: 'https://example.com' }
    };

    ws.send(JSON.stringify(command));
  });

  ws.on('message', (data) => {
    console.log('받은 데이터:', data);
  });

})();

위 CDP를 활용하면 페이지 조작 및 이동, 콘솔 출력 수집, 스크린샷 및 PDF 생성, 네트워크 트래픽 감시, 디버깅(브레이크포인트 설정, 디버깅 이벤트 감지), 성능 측정(로딩 시간, 메모리 사용량 분석)이 가능합니다.

Puppeteer 클러스터링 (병렬 처리)

puppeteer-cluster를 사용하면 여러 페이지를 동시에 병렬로 처리할 수 있습니다.

웹 스크래핑이나 테스트 자동화 작업에서 병렬 처리로 성능을 극대화합니다.

주요 특징

  • 병렬 작업 실행
  • 작업 큐 관리(작업을 자동으로 큐에 넣고, 사용 가능한 Worker에 분배합니다.)
  • 리소스 관리(브라우저 인스턴스를 효율적으로 관리하여 메모리 사용량을 줄입니다.)

설치

npm install puppeteer puppeteer-cluster

사용법

const { Cluster } = require('puppeteer-cluster');

(async () => {
  // Cluster 생성: 병렬로 4개의 작업을 처리
  const cluster = await Cluster.launch({
    concurrency: Cluster.CONCURRENCY_CONTEXT, // 컨텍스트 기반 동시 실행
    maxConcurrency: 4, // 동시에 실행할 최대 Worker 수
  });

  // 작업 정의
  await cluster.task(async ({ page, data: url }) => {
    await page.goto(url, { waitUntil: 'networkidle2' });
    const screenshotName = url.replace(/[^a-zA-Z]/g, '_') + '.png';
    await page.screenshot({ path: screenshotName });
    console.log(`스크린샷 저장 완료: ${screenshotName}`);
  });

  // 작업 큐에 URL 추가
  cluster.queue('https://example.com');
  cluster.queue('https://google.com');
  cluster.queue('https://github.com');

  // 모든 작업이 완료될 때까지 대기
  await cluster.idle();
  await cluster.close();
})();

데이터 수집 예제

const { Cluster } = require('puppeteer-cluster');

(async () => {
  const cluster = await Cluster.launch({
    concurrency: Cluster.CONCURRENCY_PAGE,
    maxConcurrency: 3,
  });

  await cluster.task(async ({ page, data: url }) => {
    await page.goto(url);
    const title = await page.title();
    console.log(`URL: ${url} -> 제목: ${title}`);
  });

  // 여러 URL을 큐에 추가
  const urls = ['https://example.com', 'https://nodejs.org', 'https://github.com'];
  urls.forEach((url) => cluster.queue(url));

  await cluster.idle();
  await cluster.close();
})();

에러 핸들링

await cluster.task(async ({ page, data: url }) => {
  try {
    await page.goto(url);
    console.log(`URL 접속 성공: ${url}`);
  } catch (err) {
    console.error(`에러 발생 [${url}]:`, err.message);
  }
});

사용자 행동 시뮬레이션

드래그 앤 드롭: page.mouse.move()와 page.mouse.down()
키보드 이벤트: page.keyboard.type()
마우스 제어: page.mouse.click()

다국어 및 로케일 설정

페이지의 언어와 로케일 설정하기.

성능 최적화 및 디버깅

리소스 최적화:

  • 불필요한 이미지 및 스타일시트 로딩 방지.
  • 요청 필터링: page.setRequestInterception().

크롬 프로파일링: 성능 병목 파악하기.
메모리 최적화: 페이지를 닫을 때 메모리 누수 방지 (await page.close()).

크롬 프로파일링

크롬 프로파일링은 Chrome DevTools를 사용하여 웹 어플리케이션의 성능, 메모리 사용량, CPU 소모 등을 분석하는 과정입니다. 이를 통해 코드 최적화, 로딩 속도 개선, 메모리 누수 진단 등을 할 수 있습니다.

주요 기능

  • Performance 프로파일링(웹 어플리케이션의 실행 시간, 렌더링 시간, 네트워크 요청 등을 분석합니다)
    Chrome DevTools > Performance 탭 > Record 시작 > 결과 분석
  • Memory 프로파일링(메모리 사용량과 메모리 누수를 확인합니다)
    Memory 탭 > Heap Snapshot 생성(Take Snapshot 클릭) > 메모리 사용량을 클래스별로 분석
  • CPU 프로파일링(함수 실행 시간 및 CPU 점유율을 분석하여 비효율적인 코드 블록을 찾아냅니다)
    Performance 탭 > Profiler 기능 활성화 > Profiler 탭에서 CPU 점유율 확인
  • Javascript 실행 분석(함수 호출 순서, 실행 시간 등을 분석해 성능 병목을 발견합니다)
  • Network 분석(요청/응답 시간, 데이터 전송량 등을 분석합니다)
    Network 탭 > 로드 시간 확인(Timing 항목에서 DNS Lookup, Initial Connection, Waiting Time 등을 확인 > Largest Contentful Paint(LCP) 페이지 렌더링 시간 측정 및 성능 병목을 찾아내기

결론

Puppeteer를 9월부터 회사에서 썼었습니다. 이제서야 라이브러리를 조금 정리했다고 생각이 듭니다. 항상 라이브러리를 분석/파악해야겠습니다.

profile
나 원장이 아니다

0개의 댓글