Pyppeteer를 활용한 웹 자동화 기술

Pyppeteer 소개

Pyppeteer는 Google이 개발한 Node.js 기반 Puppeteer의 Python 포팅 버전으로, 일본 개발자에 의해 비공식적으로 구현되었습니다. 이 도구는 Chromium 브라우저 엔진을 기반으로 하여 웹 페이지 렌더링과 자동화 작업을 수행할 수 있습니다.

Chrome과 Chromium은 동일한 렌더링 엔진을 공유하며, 기능상 거의 차이가 없어 실용적인 관점에서 개발용과 정식 버전 정도로 구분됩니다.

환경 설정 및 설치

pip install pyppeteer

Python 3.5 이상의 비동기 지원 환경이 필요합니다.

import pyppeteer
print(pyppeteer.__chromium_revision__)  # Chromium 버전 확인
print(pyppeteer.executablePath())       # Chromium 경로 확인

Chromium 다운로드 문제가 발생하는 경우, 다음 링크에서 직접 다운로드 가능합니다:

기본 사용 예제

from pyppeteer import launch
import asyncio
import time

async def search_example():
    # 브라우저 시작 (GUI 모드)
    browser = await launch(headless=False, args=['--disable-infobars','--window-size=1920,1080'])
    page = await browser.newPage()
    
    # 웹사이트 접속
    await page.goto("http://www.baidu.com/")
    
    # 검색어 입력 및 제출
    await page.type('#kw', 'pyppeteer')
    await page.click('#su')
    
    time.sleep(3)
    await browser.close()

asyncio.get_event_loop().run_until_complete(search_example())

주요 구성 옵션

옵션명 설명 기본값
ignoreHTTPSErrors HTTPS 오류 무시 여부 False
headless 헤드리스 모드 실행 여부 True
slowMo 작업 속도 조절 (밀리초) 0
devtools 개발자 도구 자동 열기 False
userDataDir 사용자 데이터 저장 경로 None

고급 설정 예제

# 브라우저 구성 파라미터
browser_config = {
    "headless": False,
    "dumpio": True,
    "userDataDir": "./user-data",
    "args": [
        '--disable-infobars',
        '--window-size=1920,1080',
        '--no-sandbox',
        '--start-maximized',
        '--proxy-server=http://localhost:1080'
    ]
}

# 뷰포트 설정
browser = await launch(headless=False, args=['--disable-infobars'])
page = await browser.newPage()
await page.setViewport({'width': 1200, 'height': 800})

# 사용자 에이전트 변경
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

# 스크린샷 캡처
await page.screenshot(path='screenshot.png')

봇 탐지 우회 기법

# WebDriver 속성 조작
await page.evaluateOnNewDocument('''
    () => {
        Object.defineProperties(navigator, {
            webdriver: { get: () => false }
        })
    }
''')

# 테스트 페이지 방문
await page.goto('https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html')

실무 응용 사례

쿠키 기반 인증 처리

async def cookie_auth_example():
    browser = await launch()
    page = await browser.newPage()
    
    await page.setUserAgent("Mozilla/5.0 ...")
    await page.setViewport({'width': 1536, 'height': 768})
    
    # 봇 탐지 우회
    await page.evaluateOnNewDocument('''
        () => {
            Object.defineProperties(navigator, {
                webdriver: { get: () => false }
            })
        }
    ''')
    
    await page.goto('https://target-site.com/login')
    
    # 쿠키 추출
    cookies_data = await page.evaluate('''() => {
        return { cookie: document.cookie }
    }''')
    
    # HTTP 요청에 쿠키 적용
    headers = {
        'user-agent': 'Mozilla/5.0 ...',
        'cookie': cookies_data.get('cookie')
    }
    
    response = requests.get(target_url, headers=headers)
    print(response.text)

페이지 스크롤 처리

# 페이지 최하단으로 스크롤
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')

# 특정 위치로 스크롤
await page.evaluate('window.scrollBy(0, 1000)')

핵심 API 함수

  • page.goto(url): URL로 이동
  • page.waitForSelector(selector): 요소 로딩 대기
  • page.querySelector(css): CSS 선택자로 요소 찾기
  • page.xpath(xpath): XPath로 요소 찾기
  • page.content(): 페이지 HTML 소스 가져오기
  • page.cookies(): 현재 쿠키 정보 얻기
  • page.evaluate(js_code): JavaScript 실행
  • page.type(selector, text): 입력 필드에 텍스트 입력
  • page.hover(selector): 마우스 호버 효과
  • page.screenshot(options): 스크린샷 캡처

데이터 추출 기법

# 단일 요소 선택 (querySelector)
element = await page.querySelector('.target-class')

# 다중 요소 선택 (querySelectorAll)
elements = await page.querySelectorAll('.target-list li')

# XPath 기반 선택
xpath_elements = await page.xpath('//div[@class="content"]//a')

# 속성 값 추출
for item in elements:
    src_value = await (await item.getProperty('src')).jsonValue()
    print(src_value)

로그인 자동화 예제

async def login_process():
    browser = await launch({
        'headless': False, 
        'args': ['--disable-infobars', '--window-size=1920,1080']
    })
    page = await browser.newPage()
    await page.setViewport({'width': 1920, 'height': 1080})
    
    # 보안 우회
    await page.evaluateOnNewDocument('''
        () => {
            Object.defineProperties(navigator, {
                webdriver: { get: () => false }
            })
        }
    ''')
    
    # 로그인 페이지 접속
    await page.goto('https://example.com/login')
    
    # 계정 정보 입력
    await page.type('#username', 'user@example.com')
    await page.type('#password', 'password123')
    
    # 로그인 버튼 클릭
    await asyncio.sleep(2)
    await page.click('#login-button', {'timeout': 3000})
    
    print('로그인 완료')

대규모 데이터 수집

async def data_collection_system():
    browser = await launch()
    page = await browser.newPage()
    await page.goto(target_url)
    
    # 페이지 로딩 대기
    await page.waitForXPath('//div[@class="data-container"]/div')
    
    # 페이지 소스 파싱
    from pyquery import PyQuery as pq
    doc = pq(await page.content())
    
    # 데이터 추출
    titles = [item.text() for item in doc('.item-title').items()]
    prices = [item.text() for item in doc('.price').items()]
    
    await browser.close()
    return titles, prices

태그: pyppeteer web-automation puppeteer chromium browser-automation

6월 11일 20:55에 게시됨