[WEB]Selenium 사용법

신동혁·2022년 8월 15일
3

WEB

목록 보기
8/8

1.Selenium이란?

셀레니움이란 웹 상에서 정적인 페이지를 탐색하는데 사용하던 beautifulsoup같은 패키지가 하지 못하는 동적인 크롤링을 지원한다. 동적인 크롤링이란 url상에는 아무런 변화없이 동작하는 웹 페이지에 대한 크롤링을 의미한다.

2.실행순서

python을 기준으로 설명한다.

1. pip나 conda를 이용해 selenium 패키지를 설치한다.

pip install selenium
# 혹은
conda install selenium

2. 사용하려는 브라우저의 웹드라이버(webdriver)를 설치한다.

  • 1) 크롬 기준으로 설명한다.
  • 2) 크롬 브라우저에서 오른쪽 상단에 존재하는 "설정(점 3개 아이콘) 기능 -> 도움말 -> Chrome 정보"에서 자신의 크롬 브라우저 버전을 확인할 수 있다.
  • 3) 해당 버전에 맞는 크롬 웹드라이버를 설치한다. 링크 : https://chromedriver.chromium.org/downloads

3. selenium 패키지에서 필요한 모듈을 호출한다.

from selenium import webdriver # webdriver를 이용해 해당 브라우저를 열기 위해
from selenium.webdriver import ActionChains # 일련의 작업들을(ex.아이디 입력, 비밀번호 입력, 로그인 버튼 클릭...) 연속적으로 실행할 수 있게 하기 위해
from selenium.webdriver.common.keys import Keys # 키보드 입력을 할 수 있게 하기 위해
from selenium.webdriver.common.by import By # html요소 탐색을 할 수 있게 하기 위해
from selenium.webdriver.support.ui import WebDriverWait # 브라우저의 응답을 기다릴 수 있게 하기 위해
from selenium.webdriver.support import expected_conditions as EC # html요소의 상태를 체크할 수 있게 하기 위해
# 이 외에도 필요한 모듈이 있다면 따로 호출해준다.

4. 웹 드라이버를 이용해 원하는 url의 웹을 브라우저로 연다.

dr = webdriver.Chrome("웹드라이버 설치된 경로")
dr.get('열려고 하는 웹 사이트 url 주소')

5. 열린 웹 브라우저를 활용해 동적 크롤링을 시작한다.

위 내용은 기본적인 부분만 설명했고 위 부분에서도 다양한 설정을 추가하거나 작업을 할 수 있다. 또한 여기서부터는 검색어 입력하는 부분을 찾고 검색어 넣어주기, 원하는 위치의 게시물 클릭하기, 특정 버튼 클릭하기 등등 너무 다양한 작업이 존재해 모든 작업에 대한 설명이 어렵다. 직접 찾아보며 실습하는 것이 좋은 것 같고 내가 실습했던 부분들에 대해서만 아래에 정리해본다.

3.여러 작업

  • 웹 페이지 요소 찾기
    (옛 버전과 차이가 있을 수 있음) 글을 작성 중인 2022/08/16 현재 쓰고있는 selenium과 구버전의 차이가 있을 수 있다. 구글링을 통해 웹 페이지 요소를 찾기 위해 find_element_by_id 같은 메서드를 사용함을 알아냈지만, 현재 버전은 by를 따로 사용하는 것으로 확인되었다. 위에서도 "from selenium.webdriver.common.by import By"를 통해 By 모듈을 따로 호출함을 확인할 수 있다.

    <find_element(By) 코드 모음>
    find_element(By.ID, "ID값")
    find_element(By.CSS_SELECTOR, "#클래스값 .아이디값")
    find_element(By.NAME, "NAME값")
    find_element(By.XPATH, "XPATH값")
    find_element(By.LINK_TEXT, "링크걸린텍스트값")
    find_element(By.PARTIAL_LINK_TEXT, "부분링크걸린텍스트값")
    find_element(By.TAG_NAME, "태그값(div, li, span ...)")
    # 이때 element 대신 elements를 이용해 여러 요소를 찾아서 리스트 형식으로 반환받는 것도 가능하다.

    @ 클래스명이 여러개일 때 해당 요소 찾기 !!!
    이때 내가 찾고 싶은 요소의 class명이 "a b c d" 이런식으로 여러개 있다면 어떻게 찾을까? 나는 이런 경우 By.CSS_SELECTOR(".a.b.c.d")이런식으로 찾았다. 만약 By.ClASS_NAME("a,b,c,d")이런식으로 찾게 될 경우 클래스명에 a,b,c,d 중 하나라도 들어간 요소를 모두 찾아 문제가 생겼었다!

  • 클릭하기

요소 = find_element(...) # 위에서 설명한 방식으로 요소를 찾아 변수로 만든다
요소.click()	
  • 키보드 입력하기
from selenium.webdriver.common.keys import Keys 
요소 = find_element(...) # 위에서 설명한 방식으로 요소를 찾아 변수로 만든다
요소.send_keys("보낼텍스트값 or Keys.요소")  

<Keys.요소 모음>
Keys.ENTER or Keys.RETURN # 엔터 입력
Keys.ARROW_DOWN # 화살표 아래 입력
Keys.BACK_SPACE # 백스페이스 입력
Keys.CONTROL # 컨트롤키 입력
... "Keys.대문자로키보드값" 형식으로 모두 비슷하다
  • 웹 브라우저의 응답 기다리기 ( NoSuchElementException, ElementNotVisibleException 해결하기 )
    selenium을 사용하다보면 해당 예외가 발생할 때가 있다. 예를 들어 구글에서 어떤 검색어를 입력하고 나온 결과 페이지에서 가장 위에 있는 게시물을 클릭하려 하는데 검색 결과 페이지 자체가 늦게 로딩되면 가장 위에 있는 게시물은 당연히 찾지 못하게 되어 예외가 발생한다. 이와 같이 크롤링을 하다보면 웹 페이지가 로딩될 때까지 기다려야 하는 경우가 발생하는데, 이때 간단하면서 살짝은 조잡하게 웹 브라우저 응답을 기다리는 방법이 있다. 이는 python의 time 모듈을 사용하는 것이다.
    1) time 모듈 사용하기

    import time
    
    time.sleep(10) # 10초 동안 멈추는 행위로, 10초 동안 웹브라우저가 로딩되길 기다리는 방식으로 이용 가능하다.

    이런 방식은 간단하다는 장점이 있지만, 무조건 설정한 시간만큼 기다려야 한다는 단점이 있다. 이런 문제점을 해결하기 위한 것이 위에서 호출했던 selenium 모듈 중 다음 모듈이다.
    2) WebDriverWait, expected_conditions(EC) 사용하기 ( Implicitly wait / Explicitly wait )

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    
    dr = webdriver.Chrome("웹드라이버 설치된 경로")
    wait = WebDriverWait(dr, 10)
    dr.get("url 주소 호출로 웹 페이지 연결")
    
    # Implicitly wait
    driver.implicitly_wait(10) # 10초 동안 기다리겠다는 의미
    
    # Explicitly wait
    wait.until(EC.element_to_be_clickable((By.NAME, "찾으려는 요소의 name값"))) # 해당 name값의 요소가 클릭할 수 있을 상태까지 기다리겠다는 의미

    위 코드에서 확인할 수 있듯 webdriverwait에는 두 가지 방식이 존재한다. 첫번째는 Implicitly wait, 두번째는 expected_conditions(EC)도 같이 사용한 Explicitly wait이다.
    Implicitly wait 방식은 위에서 설명한 time 모듈과 흡사하다. 그저 설정한 시간만큼 기다리는 것이다.
    Explicitly wait 방식은 좀 더 개선된 방식이다. 먼저 최대로 기다릴 수 있는 시간을 "wait = WebDriverWait(dr, 10)"과 같은 방식으로 정해주고, 이 시간 동안 "wait.until(EC.element_to_be_clickable((By.NAME, "찾으려는 요소의 name값")))"과 같은 코드로 내가 원하는 상태가 되기를 기다리다 해당 상태가 되면 다음 코드로 넘어가고, 설정했던 최대 기다림 시간이 넘으면 TimeoutException을 발생시키는 방식이다. 이때 Explicitly wait의 원하는 상태로는 다음과 같은 것들이 존재한다.

    <EC용 코드 모음>
    EC.title_is(...)
    EC.title_contains(...)
    EC.presence_of_element_located(...) # 내가 많이 썼던 코드1
    EC.visibility_of_element_located(...)
    EC.visibility_of(...)
    EC.presence_of_all_elements_located(...)
    EC.text_to_be_present_in_element(...)
    EC.text_to_be_present_in_element_value(...)
    EC.frame_to_be_available_and_switch_to_it(...)
    EC.invisibility_of_element_located(...)
    EC.element_to_be_clickable(...) # 내가 많이 썼던 코드2
    EC.staleness_of(...)
    EC.element_to_be_selected(...)
    EC.element_located_to_be_selected(...)
    EC.element_selection_state_to_be(...)
    EC.element_located_selection_state_to_be(...)
    EC.alert_is_present(...)

    위에서 내가 많이 썼던 코드는 두 가지다. 예제를 통해 설명한다.
    EC.presence_of_element_located()

    next_btn = wait.until(EC.presence_of_element_located((By.CLASS_NAME,"abcd")))

    해당 코드는 html요소 중 class값이 abcd인 요소가 위치함이 확인될 때(해당 요소가 로딩되었을 때라고 받아들였다)까지 기다리다 확인이 되면 해당 요소를 next_btn이라는 변수로 초기화하는 코드다.
    EC.element_to_be_clickable(...)

    next_btn2 = wait.until(EC.element_to_be_clickable((By.CLASS_NAME,"abcd")))

    해당 코드는 html요소 중 class값이 abcd인 요소가 클릭이 가능함이 확인될 때까지 기다리다 확인이 되면 해당 요소를 next_btn2라는 변수로 초기화하는 코드다.

1개의 댓글

comment-user-thumbnail
2024년 6월 10일

공식 문서보기 너무 귀찮았는데 감사합니다 떠흣

답글 달기