본문 바로가기
TOP
데이터 스킬업/웹크롤링

[ep01:웹크롤링] #17 셀레니움 로딩될 때까지 시간/조건 설정하기 with 파이썬

by 티챠림 2021. 8. 5.

a[왕초보 웹크롤링 무작정 따라하기] 웹크롤링, 셀레니움, 시간 조절, 대기시간, 동작 조건, implicitly_wait, WebDriverWait


업무지옥을 탈출한 건에 대하여(feat.업무자동화) 

#17 셀레니움 동작시간/조건 설정하기


implicitily_wait와expected_conditions (바로가기 Click)

인스타그램 크롤링 코드에 적용해보기 (바로가기 Click)



요소와 좌표를 사용하여 동작을 실행하고, 스크롤을 자유자제로 조종할 수 있게 되었다. 하지만 여기서 한 가지만 더 익힌다면 크롤링의 효율을 극대화 할 수 있다. 극대화의 기준 '시간'이다. time_sleep()으로 고정적인 시간을 대기하는 것은 매우 비효율적이다. 페이지가 로딩되어도 지정된 시간을 채워야 하고, 지정된 시간 안에 로딩되지 않으면 오류가 발생한다. 

 


implicitily_wait와 expected_conditions


 

효율을 높이기 위해서는 동작이 실행되거나 로딩되었을 때 바로 다음 동작을 수행하고, 로딩되지 않았다면 로딩될때 까지 기다렸다가 끝나면 실행되게끔 만들어야 한다. 그리고 셀레니움 모듈 중에는 이러한 시간/조건 설정 기능들을 가진 클래스들이 존재한다. implicitily_wait()expected_conditions이다. 이 클래스들을 사용하기 위해 먼저 모듈을 추가해줘야 한다.

 

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

 


 

implicitily_wait()는 페이지가 로딩되었는지를 확인하고 로딩이 되면 바로 다음 동작을 실행한다. implicitily_wait(5)로 설정하면 로딩 될때까지 최대 5초까지 기다리고, 1초만에 로딩되면 바로 다음 코드를 실행한다. time.sleep(5)는 무조건 5초를 기다리는 반면 implicitily_wait(5)는 빠르면 0.1만에 다음코드를 실행할 수 있다. 

 

# 무조건 5초 대기
time.sleep(5)

# 로딩 후 다음 동작 실행, 최대 5초까지 대기
dr.implicitly_wait(5)

 

 

 

 

expected_conditions은 조건을 설정하고 조건에 부합하는지 안하는지를 판단한다. expected_conditions으로 설정할 수 있는 주요 조건들은 아래와 같다. 괄호 안에 들어가는 By.는 확인하려는 요소가 어떤 속성인지 정의하고 ""안에 확인하려는 요소의 경로나 이름을 넣으면 된다. 예를 들어, .presence_of_element_located((By.CSS_SELECTOR ,"선택자 경로"))는 지정한 선택자 요소가 현재 페이지에 있는지 확인하는 조건이다. 

 

expected_conditions.presence_of_element_located((By. ,"")) 로딩된 페이지에 조건 요소가 있는지 확인
expected_conditions.visibility_of_element_located((By. ,"")) 로딩된 페이지에 조건 요소가 보이는지 확인
expected_conditions.presence_of_all_elements_located((By. ,"")) 로딩된 페이지가 조건 요소 중 하나라도 있는지 확인
expected_conditions.element_to_be_clickable((By. ,"")) 조건 요소가 클릭 가능한지 확인

 

expected_conditions는 조건 자체이기에 단독으로 사용할 수 없다. 조건이 부합할 때까지 기다리는 전체 코드는 WebDriverWait(dr,5).untill(expected_conditions.presence_of_element_located(By.CSS_SELECTOR ,"선택자 경로"))이다.이 코드를 전부 적기에는 복잡하고 눈에 잘 들어오지 않기에 WebDriverWait와 expected_conditions은 미리 짧은 이름으로 정의해준다. (expected_conditions는 보통 모듈을 불러올때 부터 EC로 정의해 준다.)

 

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

dr = webdriver.Chrome()
wait = WebDriverWait(dr, 5)

wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "경로 또는 이름")))

 

 


인스타그램 크롤링 코드에 적용해보기


인스타그램 크롤링 코드의 시간을 단축시켜 보자. 페이지 로딩 대기시간을 implicitly_wait()으로 바꿨고, 로그인 후 팝업이창의 버튼이 확인되면 다음 동작이 진행되도록 EC조건을 적용했다. 이런식으로 특정 요소의 로딩엽부를 확인하고 다음 코드를 실행하게 하면 로딩문제로 발생하는 오류를 대부분 줄일 수 있다. 

 

# 라이브러리 활성화
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 1.웹 열
dr = webdriver.Chrome()
wait = WebDriverWait(dr, 5)
dr.set_window_size(414, 800)
dr.get('https://www.instagram.com/')
dr.implicitly_wait(5)


# 2.로그인
id_box = dr.find_element_by_css_selector("#loginForm > div > div:nth-child(1) > div > label > input")
password_box = dr.find_element_by_css_selector("#loginForm > div > div:nth-child(2) > div > label > input")
login_button = dr.find_element_by_css_selector('#loginForm > div > div:nth-child(3) > button')

act = ActionChains(dr)

act.send_keys_to_element(id_box, '아이디').send_keys_to_element(password_box, '비밀번호').click(
    login_button).perform()
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#react-root > div > div > section > main > div > div > div > div > button')))

 

 

이전에 넣었던 모든 time.sleep()코드를 implicitily_wait()와 wait.untill(EC.~)로 바꾸었다. 피드 전체를 훑는데 10분이 걸리던 게 5분안에 끝낼 정도로 빨라지고 로딩오류도 제로...! 속도와 안전성을 모두 잡은 효율up 성공!

 

이제 인스타그램 크롤링의 마지막 단계, 데이터 추출만이 남았다. 데이터를 추출해서 엑셀로 저장하는 식을 추가할 차례다.

 

- 계속 -

 

 


[system] '주문 가속'을 성공하였습니다.

'스킬: 주문 가속' 획득

 

[보유 스킬]

동작제어, 자바스크립트 활용,

주문가속, 주문중첩, 주문연계, 

데이터시각화, 데이터필터링, 웹데이터 소환

 

[보유 칭호]

브라우저를 제어하는 자, 웹데이터를 불러내는 자


댓글