Daily Life of BlueRose

컴퓨터 & 코딩 공부/파이썬

파이썬 웹자동화 - 셀레늄 및 관련 라이브러리 기본 사용법

푸른로즈 2024. 4. 19. 11:51
728x90

개요

셀레늄은 크롬 뿐 아니라 다양한 웹브라우저를 자동화하여, 각종 웹페이지에서의 업무 처리를 자동화하는 라이브러리입니다. 웹을 자동화한다면 대부분 셀레늄을 사용하지 않을까 싶네요~!

 

물론 셀레늄 외에도 다른 크롤링, 자동화 툴이 있지만, 셀레늄이 가진 장점인 보이는 웹페이지를 직접 제어하는 점과 그로 인하여 초보자도 쉽게 접근이 가능하다는 점이 있기에 비교적 많이 사용되는 것 같습니다.

  1. 용도 : 크롤링 및 웹 자동화
  2. 설치
    • 기반 파일 설치 : google 크롬드라이버를 다운로드 받아, 압축해제 후 실행하려는 파이썬 스크립트에 넣어준다(같이 안넣을 경우 별도의 경로지정 필요) ※ 링크 : https://chromedriver.chromium.org/downloads
    • 모듈설치 : pip install selenium

 

 

크롬 디버거 열기(os.system 활용)

  1. 목적 : 열어둔 크롬 윈도우를 지속적으로 활용하기 위하여 필요하다. 이 옵션이 없는 경우엔 스크립트 작동 시 일부 기능에서 매번 새로운 창이 열린다. 다만, 크롬의 세부옵션을 조절하여 사용하는 prefs 등 변수를 사용할 수 없으므로, 경우에 따라서는 차라리 새로운 창을 띄우고 그때그때 WindowHandle을 이용하여 닫는 편이 낫을수도 있다.
  2. 예시
import os							#크롬 디버거 창 열기를 위함(CMD작동용)
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options		#크롬 디버거 내부 옵션기능 활성화를 위함

os.system('cmd /c "start chrome.exe —remote-debugging-port=9222 —user-data-dir="C:\ChromeTEMP""')  #디버거 창 켜기
time.sleep(2)

chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")		#디버거 주소를 활성화함
chrome_driver = Service(BASE_ROUTE + "\chromedriver.exe")				#크롬드라이버 주소할당
driver = webdriver.Chrome(service = chrome_driver, options=chrome_options)		#실제 드라이버 할당

 

728x90

페이지 열기(webdriver.chrome(url))

from selenium import webdriver
driver = webdriver.chrome(service = chrome_driver, options=chrome_options)
url = 'http://google.com'
driver.get(url) 
  1. 설명 : 크롬 웹드라이버를 변수로 불러와 파이썬에 연동함으로써 셀레늄의 기반으로 사용한다.
  2. 인수 : 크롬드라이버 위치를 인수로 제공가능하나, 같은 폴더내에 비치한 경우에는 별도로 입력하지 않아도 된다. 크롬드라이버를 변수로 선언할때는 try/except문을 활용할 수 없으므로, 배포를 염두해 둔다면 폴더에 파일이 있는지를 먼저 확인하도록 안내하는 편이 좋다.
  3. 웹드라이버 조작 : 웹드라이버는 추후 조작을 위하여 webdriver.chrome()를 변수에 담아 사용한다.
  4. 특정 페이지로 이동 : driver.get()을 사용한다.

문구입력(.send_keys/Keys)

from selenium.webdriver.common.keys import Keys
driver.find_element(by=By.CSS_SELECTOR, value=''.클래스명.속성명').send_keys('보낼문구') 
driver.find_element(by=By.CSS_SELECTOR, value=''.클래스명.속성명').send_keys(Keys.CONTROL, "v") 
driver.find_element(by=By.CSS_SELECTOR, value=''.클래스명.속성명').send_keys(Keys.ENTER)
  1. driver.find_element…에서 element가 단수인 경우에는 가장 처음 찾아지는 하나의 값을 선택하며, 복수인 경우에는 여러개의 값들을 모두 찾아 배열의 형태로 반환한다. 인덱스 삽입을 통해 순서에 따라 불러올 수 있다.
    • ex) …elements_by_css_selector(’.클래스명.속성명’)[i]
  2. 여러 메소드가 많으나, css_Selector가 비교적 정확도가 높고 자세한 경로 설정이 가능한 편이다.
  3. Send_keys() / Keys
    • 사용방법
      • 인수로 '문자’를 입력하는 경우 해당 글자를 그대로 입력한다.
      • 인수로 Keys.Enter 등 특정 키를 입력하는것도 가능하다.
    • 사이트가 Send_Keys를 막는 경우 : 특별히 Send_Keys가 잘 작동하지 않는 경우는 많지 않으나, 가끔 Send_Keys를 사용해도 어떠한 변화가 없는 사이트가 있다. 이런 경우엔 클립보드 복사/붙여넣기를 활용할 수 있다. pyperclip.copy(“TEXT”)를 이용하여 복사 후, Send_Keys(Keys.Control, “v”)를 이용하여 붙여넣는다.
    • 파일업로드형 Input 태그의 경우에도 Send_key를 통해 String을 해당 태그로 입력할 수 있다. 복잡하게 업로드 버튼을 눌러 파일을 넣는 형태로 진행하지 않아도 된다.
  4. Click() : 선택된 개체를 클릭한다.

여러 절차 한번에 처리하기(ActionChains)

from selenium.webdriver.common.action_chains import ActionChains
action = ActionChains(driver)
action.send_keys('Keys').perform()
  1. 사용방법
    • css_selector 등을 통해 사이트 이동 후, 웹사이트에 의해 자동으로 이동된 커서위치 등을 활용하기 위해서는 ActionChain을 활용해야한다.
    • 메서드 여러개를 이어서 연속 동작으로 사용가능하며, 가장 마지막에는 .perform()으로 실행여부를 명시해주어야 한다.
    • 1회 Action 사용후에는 action.reset_actions()를 사용하여, Chain을 초기화해 주어야 한다. 만약 그렇지 않으면 일정 조건하에 오류가 발생한다.
    • time.sleep을 중간에 넣기 힘든관계로, pause(time)이라는 별도 메서드를 사용한다.
    • .move_to_element(SELECTED).click() : 종종 get_elements_by_css_selector를 통해 특정 개체를 선택해도 정작 클릭 명령 처리가 제대로 이뤄지지 못하는 버튼들이 있다. 이는 스크롤을 내려 화면에 해당 개체가 보여야만 작동하는 상황인데, 이러한 경우에는 ActionChain 방식을 활용하면 해당 개체에 포커스가 잡히면서 실행이 가능해 진다.
  2. 주의사항
    • action.명령어()를 여러번 입력하면, action 인스턴스 내에 해당 명령어가 축적되는 구조이며, perform 수행시 그간 입력한 동작이 한번에 진행된다.(한 동작 수행 후 reset_actions()가 필요한 이유가 여기에 있다)
    • action의 명령어에 변수 등을 넣어도, 그때그때 갱신되지는 않는다. 변수는 최종 결과값의 형태로 상수로 action에 입력되므로, 반복동작을 위해 필요한 경우에는 for문에서 매번 신규로 선언을 해주어야 한다.

 

시간 대기방법 (time.sleep / driver.implicitly_wait 등)

  1. time.sleep(TIME) : 정해진 시간만큼 기다린다. import time 필요
  2. driver.implicitly_wait(TIME) : 직후 URL 탐색시 TIME 시간만큼 기다리는 것을 원칙으로 하되, 웹화면이 전부 표기가 된 경우에는 10초 미만일 경우에는 남은 시간을 skip하고 즉시 다음 명령을 시행한다.
  3. 예시 - 특정 개체가 페이지 내에 존재하는 것이 확인될때까지, 최대 TIME만큼의 시간을 기다리는 코드. 정확한 시간대기가 가능하나, 코딩이 길어지는 단점이 존재한다.
from selenium.webdriver.common.by import By			#from에서는 소문자, import에서는 대문자임에 주의
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, TIME)_
.until(EC.presence_of_element_located((By.CSS_SELECTOR, '특정개체')))	#By.CSS_SELECTOR는 by부분을 제외한 나머지 대문자임에 주의

 

팝업창 닫기

  1. driver.window_handles : 현재 열린 탭을 확인한다. print를 이용하여, 리스트의 형태로 확인도 가능하다.
  2. driver.switch_to.window(driver.window_handles[INDEX] : 특정 탭으로 활성창을 옮긴다. 창을 닫은 후 본래의 창을 다시 활성화해주지 않은 채로 특정 명령을 수행하는 경우에는 해당탭이 이미 닫혔다는 내용의 오류가 발생한다. Index를 –1로 입력하면, 최신창(탭)으로 이동한다.
  3. 예시 : 주요 창 외 나머지 모두 닫기
if len(driver.window_handles)>1:				#driver의 창이 여러개인지 확인하여, 1개 이상인 경우 작동
    for i in range(1, len(driver.window_handles)):
        driver.switch_to.window(driver.window_handles[1])		
        driver.close()
    driver.switch_to.window(driver.window_handles[0])
else: pass

 

프레임 조작하기 (특정 CSS_Selector가 파이썬에서 조회되지 않을 때)

  1. 프레임 존재여부 확인하기 : len(driver.find_elements_by_css_selector(“frame”))
  2. 프레임 명단 받기
frames = driver.find_elements_by_css_selector("frame")
for frame in frames:
    print(frame.get_attribute('name'))
  1. 프레임 전환하기
    • 하위 프레임으로 이동 : driver.switch_to.frame(‘프레임 이름’)
    • 상위 프레임으로 이동 : driver.switch_to_default_content
    • 주의사항
      • 로그인 등 특정 행동시 프레임 이동 내역이 해제되는 것으로 보인다.
      • 태그가 상, 하위가 있듯, 프레임도 상위 프레임, 하위 프레임이 존재한다. 하위 프레임에 접근할때에는 상위 프레임부터 차근차근 경로에 따라 이동해야 한다.
      • 하위 프레임 목록에 지정한 명칭의 프레임이 존재하지 않을 경우, 약 5~10초 정도의 딜레이와 함께 오류가 발생한다. 따라서, 로그인 등 행동으로 인한 프레임 이동 내역 해제에 대비하기 위하여는 try / except 문이나 if문을 활용하여 대비해야 한다.
반응형