DrissionPage(이하 DP)는 Selenium의 번거로움을 해결하고자 설계된 웹 자동화 도구로, 브라우저 기반 스크레이핑과 순수 HTTP 요청을 모두 지원한다. 본문에서는 실무에 바로 적용할 수 있는 핵심 기능을 중심으로 살펴본다.
환경 구성 및 모듈 임포트
패키지 설치 후 주요 모듈은 다음과 같이 가져온다.
# 터미널에서 설치
# pip install DrissionPage
from DrissionPage import Chromium # 브라우저 제어
from DrissionPage.common import By # 요소 탐색 전략
브라우저 인스턴스 생성과 페이지 탐색
Chromium 기반 브라우저를 실행하고 대상 URL로 이동하는 기본 패턴이다.
from DrissionPage import Chromium
import time
browser = Chromium()
browser.get('https://www.baidu.com')
요소 탐색 전략
단일 요소 접근
ele() 메서드에 검색 전략과 선택자를 담은 튜플을 전달한다. 반환된 객체에 대해 입력, 클릭 등의 조작이 가능하다.
# 검색창에 텍스트 입력
search_input = browser.ele((By.XPATH, '//textarea[@id="chat-textarea"]'))
search_input.input('원피스')
# 전송 버튼 클릭
submit_btn = browser.ele((By.XPATH, '//button[@id="chat-submit-button"]'))
submit_btn.click()
복수 요소 순회
eles()로 컬렉션을 받아 순회하며 하위 요소를 재탐색할 수 있다. 인덱스 기반 접근 시 주의할 점은 DP가 1부터 시작한다는 것이다.
browser.get('https://movie.douban.com/top250')
film_items = browser.eles((By.XPATH, '//ol[@class="grid_view"]/li'))
for entry in film_items:
name = entry.ele((By.XPATH, './/span[@class="title"]')).text
link = entry.ele((By.XPATH, './/div[@class="info"]/div/a')).attr('href')
print(name, link)
동적 대기 처리
명시적 대기 없이 요소 유무를 조건문으로 판단할 수 있다. 타임아웃 내 미발견 시 False를 반환한다.
# 요소 로딩 여부 확인 (2초 대기)
is_loaded = browser.wait.eles_loaded((By.XPATH, '//textarea[@id="nonexistent"]'), timeout=2)
print(is_loaded) # False
인증 플로우 자동화
DP는 iframe 내부 요소도 직접 탐색 가능하며 별도 전환 과정이 불필요하다.
from DrissionPage import Chromium
from DrissionPage.common import By
driver = Chromium()
driver.get('https://www.douban.com/')
# 계정 탭 선택
driver.ele((By.CLASS_NAME, 'account-tab-account')).click()
# 자격 증명 입력
driver.ele((By.ID, 'username')).input('your_username')
driver.ele((By.ID, 'password')).input('your_password')
# 텍스트 기반 요소로 로그인 트리거
driver.ele((By.LINK_TEXT, '登录豆瓣')).click()
driver.quit()
네트워크 트래픽 가로채기
브라우저와 서버 간 XHR/Fetch 통신을 가로채 API 응답을 직접 확보할 수 있다. 이는 프론트엔드 렌더링 대응 및 JS 역분석 부담을 크게 줄여준다.
from DrissionPage import Chromium
from DrissionPage.common import By
crawler = Chromium()
# 페이지 로드 전 리스너 등록
crawler.listen.start('mvc/getNoticeList4Web.do')
crawler.get('http://www.ccgp-hunan.gov.cn/page/notice/more.jsp')
page_num = 0
for packet in crawler.listen.steps(count=10):
if crawler.wait.eles_loaded((By.LINK_TEXT, '下一页'), timeout=3):
crawler.ele((By.LINK_TEXT, '下一页')).click()
page_num += 1
print(f'[페이지 {page_num}] {packet.response.body}')
else:
print('더 이상 페이지 없음, 수집 종료')
break
crawler.quit()
복합 동작 체인
드래그 앤 드롭, 마우스 이동 등 복합 제스처를 메서드 체이닝으로 구성한다. 슬라이드 캡차 우회 시 유용하다.
crawler.get('https://www.ynjzjgcx.com/mohurd/data-query/enterprise?keyword=小米')
# 팝업 닫기
crawler.ele((By.XPATH, '//span[@class="verifybox-close"]')).click()
# 슬라이더 핸들 탐색
handle = crawler.ele((By.XPATH, '//div[@class="verify-move-block"]/i'))
# 300px 우측으로 드래그
crawler.actions.hold(handle).right(300).release()
실제 적용 시에는 ddddocr 등 OCR 라이브러리로 이동 거리를 동적 계산하여 right() 인자로 전달해야 한다.
SessionPage: 헤드리스 HTTP 클라이언트
브라우저 오버헤드 없이 순수 세션으로 REST API를 호출할 수 있다.
from DrissionPage import SessionPage
endpoint = 'http://www.ccgp-hunan.gov.cn/mvc/getNoticeList4Web.do'
payload = {
'pType': '',
'prcmPrjName': '',
'startDate': '2025-01-01',
'endDate': '2025-12-04',
'page': '1',
'pageSize': '18',
}
client = SessionPage()
client.post(endpoint, data=payload)
print(client.response.json()) # JSON 파싱
client.close()