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 다운로드 문제가 발생하는 경우, 다음 링크에서 직접 다운로드 가능합니다:
- Linux: https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/575458/chrome-linux.zip
- Mac: https://storage.googleapis.com/chromium-browser-snapshots/Mac/575458/chrome-mac.zip
- Windows: https://registry.npmmirror.com/binary.html?path=chromium-browser-snapshots/
기본 사용 예제
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