Python/Selenium

Python + Selenium을 이용한 웹 자동화

navill 2020. 2. 25. 17:08

Chrome 브라우저와 Selenium을 이용해 간단한 웹 사이트를 동작시켜보는 예제를 정리해보았다. 

 

Selenium with Python

공식 문서

Selenium with Python - Selenium Python Bindings 2 documentation

# selenium 설치
pip install selenium

 

크롬 설정

  • 현재 사용중인 크롬 버전확인

 

자동 검색어 입력

  • 자동으로 구글에 접속하여 'selenium'을 검색하는 기능 구현

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

# Chrome
driver = webdriver.Chrome('/Users/jh/Desktop/Python/selenium/Chrome_Driver/chromedriver')
# Firefox
# driver = webdriver.Firefox()
# Intenet explorer
# driver = webdriver.Ie()

wait = WebDriverWait(driver, timeout=1)
driver.get("https://google.com/")
mid_result = wait.until(presence_of_element_located((By.CLASS_NAME, "gNO89b")))
driver.find_element_by_name("q").send_keys("selenium" + Keys.RETURN)

first_result = wait.until(presence_of_element_located((By.CLASS_NAME, "rc")))
print(first_result.get_attribute("textContent"))
"""
HowToMakeWebCrawler-With-Selenium저장된 페이지2017. 2. 26. - Selenium은 주로 웹앱을 
테스트하는데 이용하는 프레임워크다. webdriver 라는 API를 통해 운영체제에 설치된 Chrome등의 브라우저를 
제어하게 ...selenium 설치selenium javaselenium 버튼 클릭크롬 드라이버 64비트selenium xpath 
사용법selenium headless함께 검색한 항목...
"""

# 검색 완료 후 크롬 창 최대화
driver.maximize_window()
# 새로고침
driver.refresh()
# 3초 후 드라이버 종료(크롬창 닫힘)
time.sleep(3)
print('Test Completed')
driver.quit()

driver = webdriver.Chrome('/Users/jh/Desktop/Python/selenium/Chrome_Driver/chromedriver')

→ site-packages에 driver 파일을 위치 시킬 경우 경로를 지정하지 않아도 된다.

 

driver.find_element_by_name("q").send_keys("selenium" + Keys.RETURN): input tag에 name='q' 속성을 이용해 검색 창에 필요한 속성값을 가져오고 입력한 값을 전달한다.

 

만일 입력에 Enter Key가 유효하지 않을 경우, 'driver.find_element_by_name('btnK').click())' 를 이용해 직접 클릭 동작을 실행시킬 수 있다.

 

UnitTest

  • HtmlTestRunner를 이용해 테스트 결과를 html 파일로 변환할 수 있다.

    → 깔끔하게 결과를 확인할 수 있음

HtmlTestRunner 설치

# HtmlTestRunner 설치
$ pip install html-testRunner
# unittest의 결과를 저장할 디렉토리
$ mkdir reports

자동 검색 코드 - keyword로 'python'과 'selenium'을 입력

  - python을 검색하는 코드에서 find_element_by_name에 알 수 없는 값 'q1'을 입력하여 의도적으로 오류 출력

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest
import HtmlTestRunner


class GoogleSearch(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome('/Users/jh/Desktop/Python/selenium/Chrome_Driver/chromedriver')
        cls.driver.implicitly_wait(10)
        cls.driver.maximize_window()

    def test_search_selenium(self):
        self.driver.get('https://google.com')
        self.driver.find_element_by_name('q').send_keys('selenium' + Keys.RETURN)

    def test_search_python(self):
        self.driver.get('https://google.com')
        # 알 수 없는 element
        self.driver.find_element_by_name('q1').send_keys('python' + Keys.RETURN)

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()
        cls.driver.quit()
        print('complete')


if __name__ == '__main__':
    # 저장할 주소 지정
    unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='/Users/jh/Desktop/Python/selenium/report'))

Result

console에 위와 같은 결과를 출력: 2개의 테스트 중 1개 에러
report 디렉토리에 저장된 html파일을 열면 위와 같은 결과를 출력한다.

 

Selenium을 이용한 자동 로그인

  • 사이트에 접속해 로그인, 로그아웃을 자동으로 실행하는 테스트 코드

    • 코드는 웹 페이지가 모두 구성될 때(실행하려는 요소가 페이지에 확인될 때) 실행 시킬 수 있으므로, 예외처리나 wait 구문에 신경써야 한다.
    • 공식 문서에서 제공하는 Expected Conditions(link)를 이용해 필요한 요소가 브라우저에 완전히 출력될 때 실행시켜야 한다.
import unittest
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class LoginTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome('/Users/jh/Desktop/Python/selenium/Chrome_Driver/chromedriver')
        # cls.driver.implicitly_wait(5)
        cls.driver.maximize_window()

    def test_login(self):
    	# default: 10초
        wait = WebDriverWait(self.driver, 10)
        self.driver.get('https://opensource-demo.orangehrmlive.com/')
        self.driver.find_element_by_id('txtUsername').send_keys('Admin')
        self.driver.find_element_by_id('txtPassword').send_keys('admin123' + Keys.RETURN)
        try:
            # welcom list가 뜰때까지 대기
            wait.until(EC.element_to_be_clickable((By.ID, "welcome")))
            self.driver.find_element_by_id('welcome').click()
            # link text('Logout')이 뜰때까지 대기
            wait.until(EC.presence_of_element_located((By.LINK_TEXT, "Logout")))
            self.driver.find_element_by_link_text('Logout').click()
 	# 10초가 넘을 경우 exception
        except Exception as e:
            print(f'raised time out exception: {e}')
        finally:
            time.sleep(2)

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()
        cls.driver.quit()
        print('Test Completed')


if __name__ == '__main__':
    unittest.main()
  • 코드를 작성할 때 웹 페이지가 모두 구성될 때(실행하려는 요소가 페이지에 확인될 때) 실행 시킬 수 있으므로, 예외처리나 wait 구문에 신경써야 한다.
  • 공식 문서에서 제공하는 Expected Conditions(link)를 이용해 필요한 요소가 브라우저에 완전히 출력될 때 실행시켜야 한다.
    • 되도록 time.sleep(), WebDriverWait().until(), driver.implicity_wait()구문을 이용해 클라이언트(브라우저)에서 렌더링이 완료될 시간을 지정해주는 것이 좋다.