셀레늄

Taehun Jeong·2023년 3월 15일
0
post-thumbnail

Selenium

셀레늄은 웹 어플리케이션 자동화, 테스트를 수행할 수 있는 프레임워크이다. Python 외 여러 언어 환경에서도 제공하고 있다. BeautifulSoup4, requests 와 달리 동적으로 웹 크롤링을 수행할 수 있다. 브라우저 자동화를 위해 웹 드라이버를 사용하며, 이를 통해 브라우저를 컨트롤할 수 있다. 크롬, 파이어폭스, 사파리 등 다양한 브라우저를 지원한다.


준비

pip install selenium
conda install selenium

먼저 셀레늄 라이브러리를 설치해주자. 현재 포스트에서 사용한 버전은 3.141.0 이다.

다음으로 사용할 브라우저의 웹 드라이버를 다운받아야 한다. 드라이버를 받기 전, 드라이버가 현재 설치되어 있는 크롬과 호환되어야 하므로 버전을 확인해야 한다. 크롬의 경우 주소에 chrome://version을 입력하여 현재 버전을 확인하자.

포스트에서 사용할 크롬의 버전은 111.0.5563.64 이다. 아래의 링크를 통해 해당 버전에 대응되는 드라이버를 찾자.

ChromeDriver

Downloads의 Currrent Releases에서 현재 사용하는 버전과 대응하는 드라이버의 다운로드 링크에 접속하면 OS 별로 브라우저를 다운받을 수 있다. Windows는 64bit에서도 32bit 버전을 사용할 수 있으므로 win32 버전을 사용한다.

from selenium import webdriver

driver = webdriver.Chrome('/crawling/chromedriver') # 드라이버 경로

셀레늄 라이브러리를 임포트하고 드라이버에 경로를 지정해줌으로써 진행할 수 있다.


Error: 'chromedriver' executable needs to be in PATH

위의 코드를 실행했더니 에러가 발생했다.

Message: 'chromedriver' executable needs to be in PATH

Chrome 브라우저 자동화에 필요한 웹 드라이버가 환경 변수에 등록되어 있지 않아 발생한 문제이다. 해결방법으로는 환경 변수에 직접 웹 드라이버가 있는 경로를 추가할 수도 있다. 또는, 절대 경로를 통해 호출하는 방법, Webdriver Manager를 설치하는 방법도 있다. Webdriver Manager를 사용하면 웹 드라이버 설치, 관리를 자동화하고 브라우저 버전이 바뀔 때마다 일일이 드라이버를 설치해야 하는 수고를 덜어줄 수 있으므로 Webdriver Manager를 사용할 수 있다.

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())

해당 커맨드를 실행하면 Webdriver Manager가 웹 드라이버를 설치하고 실행할 것이다.


Selenium 메서드

URL 이동

driver.get("https://www.google.com") # URL 주소

get() 메서드에 URL 주소를 입력하면 해당 주소에서 탐색을 진행할 수 있다.

선택 요소 찾기

주어진 조건에 부합하는 요소를 찾으려면 find_element_by_를 사용한다.

element = driver.find_element_by_xpath("//input[@name='q']")
# XPath를 사용하여 요소를 찾는다.

element = driver.find_element_by_id("element_id")
# ID를 사용하여 요소를 찾는다.

element = driver.find_element_by_name("element_name")
# 이름을 사용하여 요소를 찾는다.

element = driver.find_element_by_class_name("element_class")
# 요소의 Class 이름을 사용하여 찾는다.

element = driver.find_element_by_css_selector("#element_id")
# CSS 선택자를 사용하여 요소를 찾는다.

element = driver.find_element_by_tag_name("element_tag")
# 태그 이름을 사용하여 요소를 찾는다.

element = driver.find_element_by_link_text(text)
# 주어진 텍스트와 일치하는 링크 텍스트를 찾는다.

element = driver.find_element_by_partial_link_text(text)
# 주어진 텍스트를 포함하는 링크 텍스트를 찾는다.

elements = driver.find_elements_by_xpath("//input[@name='q']")
# XPath를 사용하여 해당되는 모든 요소를 찾는다.

elements = driver.find_elements_by_css_selector(query)
# CSS 선택자를 사용하여 해당되는 모든 요소를 찾는다.

elements = driver.find_elements_by_class_name("element_class")
# 요소의 Class 이름을 사용하여 해당되는 모든 요소를 찾는다.

elements = driver.find_elements_by_tag_name("element_tag")
# 태그 이름을 사용하여 해당되는 모든 요소를 찾는다.

frame = driver.find_element_by_xpath("//iframe[@name='iframe_name']")
driver.switch_to.frame(frame)
# XPath를 사용하여 프레임을 선택하고, 해당 프레암으로 이동
# 프레임(Frame)이란 독립적인 HTML 문서로 구성된 다른 웹 페이지를 현재 웹 페이지 내에 포함시켜 보여주는 기능

driver.switch_to.alert
# Alert 창으로 이동

이벤트 실행하기

선택된 요소에 이벤트를 부여할 수 있다.

element.send_keys("search keyword")
# 입력 요소에 값을 입력한다.

element.clear()
# 입력 요소의 입력된 값을 지운다.

element.click()
# 요소를 클릭한다.

value = element.get_attribute("attribute_name")
# 요소의 속성 값을 가져온다.

text = element.text
# 요소의 텍스트 값을 가져온다.

driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 요소에 JavaScript 코드를 실행한다. 실행할 코드를 파라미터로 전달한다.

element.is_displayed()
# 요소가 화면에 출력되었는지 확인한다.

element.is_enabled()
# 요소가 활성화되어 있는지 확인한다.

element.is_selected()
# (체크박스 등) 요소가 체크된 상태인지 확인한다.
from selenium.webdriver.common.alert import Alert

Alert(driver).accept()
# Alert창 수락
Alert(driver).dismiss()
# Alert창 거절
print(Alert(driver).text)
# Alert창 텍스트 출력

탐색 조작

셀레늄을 사용하여 탐색을 자동화할 때, 웹 페이지의 로딩에 시간이 걸리거나 AJAX 등을 활용한 동적 페이지의 경우, 이를 처리하기 위한 대기 기능을 제공한다.

driver.implicitly_wait(10)
# 10초 동안 묵시적 대기를 실행한다.
# 묵시적 대기란 특정 작업을 수행하기 전에 지정된 시간 동안 웹 페이지의 로딩을 대기하는 것을 말한다.
# 지정된 시간이 만료되기 전에 웹 페이지가 로딩되거나, 만료되면 다음 동작을 수행한다.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get(URL)

element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'element_id')))
# "element_id" ID를 가진 DOM 요소가 페이지에 존재할 때까지 최대 10초간 명시적 대기를 실행한다.
# 10초 동안 TimeoutException이 발생하면서 500ms마다 ExpectedCondition을 호출한다.
# 만약 10초가 지난 후에도 요소를 찾을 수 없을 경우 실패를 반환한다.
# 해당 요소를 찾게 되면 해당 요소를 반환한다.

다음은 셀레늄에서 제공하는 ExpectedCondition의 종류이다.

EC의미
title_is페이지의 title이 일치하면 True, 그렇지 않으면 False
title_contains페이지의 title에 대소문자를 구분하여 해당 문자열이 포함되어 있는지 확인. 포함되면 True, 그렇지 않으면 False
presence_of_element_located페이지에 DOM 요소가 있는지 확인
visibility_of_element_located요소가 페이지의 DOM에 있고 볼 수 있는 상태인지 확인
visibility_ofDOM 요소가 보이는지 확인
presence_of_all_elements_located페이지에 적어도 하나의 요소가 있는지 확인
text_to_be_present_in_element주어진 텍스트가 지정된 요소에 있는지 확인
text_to_be_present_in_element_value주어진 텍스트가 지정된 요소(input box 등)에 있는지 확인
frame_to_be_available_and_switch_to_it주어진 프레임을 전환할 수 있는지 확인
invisibility_of_element_located페이지에 DOM 요소가 보이지 않거나 존재하지 않는지 확인
element_to_be_clickable페이지에 DOM 요소가 보이고, 클릭 가능한지 확인
element_to_be_selectedDOM 요소가 선택 가능한지 확인
element_located_to_be_selectedDOM 요소가 선택 가능한 위치에 있는지 확인
element_selection_state_to_beDOM 요소가 선택되었는지 확인
element_located_selection_state_to_be요소를 찾고, 선택된 상태인지 확인
staleness_of요소가 DOM에 연결되어 있지 않은지 확인. DOM에 연결되어있으면 False, 그렇지 않으면 True
alert_is_present알림이 있는지 확인

브라우저 제어

driver.back()
# 이전 페이지로 이동
driver.forward()
# 다음 페이지로 이동

driver.maximize_window()
# 브라우저 창 크기 최대화
driver.minimize_window()
# 브라우저 창 최소화

print(driver.title)
# 현재 브라우저의 제목 출력
print(driver.current_url)
# 현재 브라우저의 URL 출력
driver.save_screenshot("screenshot.png")
# 현재 페이지의 스크린샷을 저장한다.

driver.close()
# 브라우저 닫기

driver.quit()
# 웹 드라이버 종료

driver.window_handles[0]
#브라우저 탭 객체를 리스트로 반환. [0]은 첫번재 탭을 의미 
driver.switch_to.window(driver.window_handles[0])
# 첫번째 탭으로 이동

Practice: 검색 자동화

다음은 구글에 접속하여 검색 창에 내용을 입력하고 탐색하는 예시이다.

driver.get("https://www.google.com")

search_box = driver.find_element_by_name("q")	# HTML 문서로부터 name이 "q"인 요소를 찾음
search_box.send_keys("Python")	# 앞서 찾은 요소에 "Python" 입력

search_box.submit()	# 제출

google 메인 페이지에서 검색창을 찾는다.

검색창은 name="q"를 통해 접근할 수 있으므로 find_element_by_name 메서드를 사용해 찾는다. 해당 input box에 "Python" 값을 입력하고 제출함으로써 검색을 수행할 수 있다.


References

정보의 공유 사회) [Python] 파이썬 selenium WebDriverException오류 해결 : selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH
고로케) [selenium] 크롤링 selenium 셀레니움 사용법, 명령어 모음
갑자기코딩) [python] 파이썬 셀레니움(selenium) #2메소드 종류
메바동 서식지) [Selenium] Selenium Waits(대기) 정리

profile
안녕하세요

0개의 댓글