Selenium은 동적 웹 사이트에 대한 지원을 진행하기 위해 명시적 기다림(Explicit Wait) 과 암묵적 기다림(Implicit Wait) 을 지원합니다.
Explicit Wait: 다 로딩이 될 때까지 지정한 시간 동안 기다림 (e.g. 다 로딩이 될 때까지 5초동안 기다려!)
Implicit Wait: 특정 요소에 대한 제약을 통한 기다림 (e.g. 이 태그를 가져올 수 있을 때까지 기다려!)
다음 사이트에 있는 행사의 이름들을 스크래핑 해봅시다 : https://indistreet.com/live?sortOption=startDate%3AASC
해당 웹 페이지는 공연 리스트가 담긴 웹 페이지입니다.
필요한 라이브러리 불러오기
# 스크래핑에 필요한 라이브러리를 불러와봅시다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
위 사이트를 확인해보니 class 이름이 조금 특이했습니다.
이는 스크래핑을 방지할 목적으로 랜덤하게 class 이름을 생성하기 때문인데요,
이러한 경우에서 쓸 수 있는 방법이 여러가지가 있는데,
그 중 한가지 방법인, 위치를 활용한 방법을 알아보도록 하겠습니다.
XPath는 XML, HTML 문서 등의 요소의 위치를 경로로 표현하는 것을 의미합니다.
마치 데스크탑/폴더1/폴더2/음악.mp3와 같이 말이죠!
이를 적용해서 데이터를 온전히 가져와봅시다.
# 예시 사이트에 요청을 진행하고, 예시 사이트의 첫 번째 이벤트의 제목을 가져와봅시다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.find_element(By.XPATH, '/html/body/div[1]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]').text
만약 데이터 처리속도와 렌더링 속도가 차이가 난다면 오류가 발생할 수 있습니다.
그런 상황을 예방하기 위하여 Wait을 사용합니다
.implicitly_wait()을 활용해서 암시적 기다림을 적용할 수 있습니다.
주의하실 점으론, 반드시 해당 시간을 기다리는 것이 아니라, 로딩이 다 될때까지의 한계 시간의 의미를 가집니다.
# 10초동안 Implicit Wait을 진행하도록 해서 스크래핑이 잘 이루어지도록 수정해봅시다.
from selenium.webdriver.support.ui import WebDriverWait
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.implicitly_wait(10)
print(driver.find_element(By.XPATH, '/html/body/div[1]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]').text)
WebDriverWait()과 두 메서드를 활용해서 명시적 기다림을 적용할 수 있습니다.
until(): 인자의 조건이 만족될 때까지
until_not() 인자의 조건이 만족되지 않을 때까지
예를 들어, id가 target인 요소가 존재할 때까지 기다린 후 다음 명령을 진행합니다.
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "target")))
이때, EC는 expected_conditions로, selenium에서 정의된 조건들입니다 (~가 존재하면, ...)
이곳에서 더 자세한 정보를 확인할 수 있습니다.
# Explicit Wait를 활용해서 스크래핑이 잘 이루어지도록 코드를 작성해봅시다.
from selenium.webdriver.support import expected_conditions as EC
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '/html/body/div[1]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]')))
print(element.text)
# 여러 공연의 제목을 스크래핑하는 코드를 작성해봅시다.
# 각 공연들의 XPath를 자세히 관찰해 보면 공연 제목들에 해당하는 XPath는 한 부분 말곤 같은 형식을 띄고있어 for문을 활용하여 여러 공연들의 제목을 가져올수 있습니다.
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.implicitly_wait(10)
for i in range(1, 11): # 1~10
element = driver.find_element(By.XPATH, '/html/body/div[1]/div/main/div[2]/div/div[4]/div[1]/div[{}]/div/a/div[2]/p[1]'.format(i))
print(element.text)