[Python] Selenium 라이브러리 (자동 웹 테스팅, 스크래핑)


Development note/Python  2020. 2. 5. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 Selenium 라이브러리에 대한 글입니다.


먼저 Selenium이란, 웹 브라이져의 드라이버에 접속하여 제어를 할 수 있게 하는 라이브러리로 보통 웹 테스팅이나 스크래핑 영역에서 자주 사용합니다.

쉽게 말해서, Python의 스크립트로 우리가 자주 쓰는 크롬 브라우져를 제어하는 것으로 특정 버튼을 자동으로 클릭하거나 이동하고 수집하여 웹 테스트나 스크래핑으로 활용할 수 있습니다.


예전에 C#으로 스크래핑에 관한 설명한 적이 있습니다.

링크 - [C#] Gecko 라이브러리 (웹 스크래핑)

여기서 사용한 Gecko라이브러리와 차이점은 Gecko 라이브러리는 브라우저 객체를 가져와서 Form 컨트럴에 붙히거나 사용하는 것으로 실제 브라우저를 제어하는 것이 아니고 브라우저의 오브젝트 라이브러리를 사용하는 것입니다.

그러나 Selenium은 브라우저의 라이브러리를 사용하는 것이 아니고 이미 PC에서 설치되어 있는 웹 브라우저를 Selenium 라이브러리를 통해 컨트럴하는 것이 차이점이 있습니다.

이는 좀 더 유저의 환경에서 움직일 수 있어서 Gecko 브라우저를 만드는 것보다 실제적인 웹 테스팅이 가능한 점이 있습니다.


이 Selenium을 사용하기 위해서는 Python에서 Selenium 라이브러리를 다운 받아야 합니다.

pip install selenium

저는 이미 설치되어있다고 표시되네요...


라이브러리를 설치했으면 이번에는 드라이버를 설치해야 합니다. 여기서는 Chrome을 통해 예제를 작성하겠습니다.

Firefox나 IE도 동일합니다.

먼저 이미 설치되어 있는 Chrome의 버전을 확인해야 합니다.

크롬 브라우저의 오른쪽 상단의 메뉴를 클릭하고 Help -> About Google Chrome을 누릅니다.

그럼 위 이미지처럼 현재 버전이 나옵니다.


아래의 링크를 타고가서 앞자리가 같은 버젼을 선택합니다.

링크 - https://sites.google.com/a/chromium.org/chromedriver/downloads

저의 경우는 79.xxx버전이었기 때문에 79.xxx를 다운 받았습니다. 그리고 윈도우에서 사용할 것이기 때문에 윈도우 버전을 다운 받았습니다.

압축 파일 안에는 chromedriver.exe 파일이 있는데 python을 실행할 파일 폴더에 드라이버를 복사해 넣습니다.

여기까지 Selenium을 사용하기 위한 준비는 끝났습니다.

이제부터 소스 작성을 해보겠습니다.

# selenium 모듈을 사용한다.
from selenium import webdriver

# driver를 읽어온다.
driver = webdriver.Chrome('chromedriver.exe');
# 크롬 브라우저에 접속할 페이지를 설정한다.
driver.get("https://nowonbun.tistory.com");
# 대기 설정. (find로 객체를 찾을 때 검색이 되지 않으면 대기하는 시간 초단위)
driver.implicitly_wait(2)

# xpath로 element를 찾는다. 이 xpath는 명월일지 블로그의 왼쪽 메뉴의 Dev note의 Javascript, Jquery, Css 카테고리다.
element = driver.find_element_by_xpath('//*[@id="leftside"]/div[2]/ul/li/ul/li[1]/ul/li[6]/a');
# 클릭한다. 사실 클릭은 element.click인데 이게 호환성 에러가 발생할 경우가 있다. 그럴 경우, 스크립트로 클릭을 설정할 수 있다.
driver.execute_script("arguments[0].click();", element);

# css selector로 "[Javascript] 팝업 라이브러리(bootbox)"의 포스트를 찾는다. 찾은 때까지 무한 루프.
while True:
  try:
    element = driver.find_element_by_css_selector("[href^='/626']");
    driver.execute_script("arguments[0].click();", element);
    break;
  except:
    # 검색된 페이지에 없으면 다음 페이지에서 검색한다.
    element = driver.find_element_by_css_selector(".paging li.active+li > a");
    driver.execute_script("arguments[0].click();", element);

# id가promptEx인 데이터를 찾는다.
element = driver.find_element_by_xpath("//*[@id='promptEx']");
# 여기서는 click이 됩니다. 아마 버튼 계열은 click이 되는데 링크 계열은 스크립트 처리를 해야 하나 봅니다.
element.click();

# 팝업의 dom을 찾는다.
element = driver.find_element_by_xpath("/html/body/div[6]/div/div/div[2]/div/form/input");
# input text에 test의 값을 넣는다.
element.send_keys('test');

# 위와 같은 dom이다.
element = driver.find_element_by_xpath("/html/body/div[6]/div/div/div[2]/div/form/input");
# 속성 value값을 출력한다.
print(element.get_attribute("value"));

# .article의 글에 p 태그의 속성을 전부 가져온다.
elements = driver.find_elements_by_css_selector(".article p");
# 출력한다.
for element in elements:
  print(element.text);
# 브라우저를 닫는다.
driver.close();

위 소스를 실행시키면 chrome 브라우저가 실행되면서 움직이기 시작합니다.

브라우저의 팝업을 실행하고 데이터를 입력하고 취득하는 것까지 확인했습니다.


그럼 좀 세부적으로 dom을 탐색하는 메소드에 대해서 알아보겠습니다.

html의 오브젝트를 취득하는 방법은 총 8가지가 있습니다.

함수명 설명
find_element_by_id 요소의 속성 id로 찾는 오브젝트를 찾습니다.
find_element_by_class_name 요소의 속성 class가 포함된 오브젝트를 찾습니다.
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 요소의 태그 이름으로 찾습니다.
find_element_by_css_selector css selector(sizzle)로 오브젝트를 찾습니다.

위 탐색 함수는 복수일 경우 모두 첫번째 요소를 가져옵니다. 복수를 찾는 방법은 함수명을 find_element에서 find_elememts로 찾으면 복수로 요소를 찾습니다.

즉, name으로 찾는 요소가 복수일 경우, find_elements_by_name의 함수를 이용하면 됩니다.


그리고 복잡한 웹일 경우, xpath를 구하기가 어려운데 이 경우는 브라우저의 개발자 모드로 하면 찾을 수 있습니다.

먼저 개발자 모드의 왼쪽 위를 클릭해서 찾고자 하는 요소를 선택하면 개발자 모드에 태그가 선택이 됩니다.

선택된 태그에서 마우스 오른쪽 클릭을 하면 copy 메뉴가 있는데 그 안에 xpath와 css selector 경로가 나오게 됩니다. 단순히 직접 경로가 나오기는 하지만 그 값을 통해서 약간의 상대 경로(?)로 수정하면 path를 찾을 수 있습니다.


그 외에 selenium에서 자주 사용하는 함수에 대해 소개하겠습니다.

함수명 설명
implicitly_wait(초 단위) 탐색시 object가 없으면 대기하는 시간.
close() 브라우저를 종료한다.
execute_script("스크립트", 요소) 해당 페이지에 스크립트를 만들 때 사용합니다. 요소는 필수 파라미터는 아니고 요소가 있으면 요소에 스크립트가 실행되고 없으면 전체 페이지에 스크립트가 움직입니다.
get_attribute("속성") 속성 값을 가져온다.
send_keys text의 경우는 값을 넣거나 key값을 넣으면 동작을 지시합니다.
키의 값은 다음 링크를 참조해 주세요.
링크 - https://selenium.dev/selenium/docs
get_cookies() 쿠키 값을 가져온다.(딕셔너리 타입)
delete_all_cookies() 쿠키를 삭제한다.
add_cookie(쿠키) 쿠키를 추가한다. (딕셔너리 타입)

아래는 잘 사용하지는 않습니다만, 사용하게 되면 참고해야할 사이트를 링크해 놓곘습니다.

액션에 관한 함수입니다.

링크 - https://selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.action_chains.html


알람에 관한 함수입니다.

링크 - https://selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.alert.html


select 요소에 관한 함수입니다.

링크 - https://selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.select.html


chrome의 설정 옵션에 관한 함수입니다.

링크 - https://selenium.dev/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html


참조 - https://www.browserstack.com/guide/locators-in-selenium

참조 - https://selenium-python.readthedocs.io

참조 - https://pythonbasics.org/selenium_cookies/


여기까지 Python에서 Selenium 라이브러리에 관한 내용였습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.