BeautifulSoup: Wait, Mouse, Keyboard를 활용한 동적 웹사이트 스크래핑
[BeautifulSoup] Wait, Mouse, Keyboard를 활용한 동적 웹사이트 스크래핑
Selenium을 이용한 동적 웹사이트 스크래핑: Wait, Mouse, Keyboard

동적 웹사이트를 스크래핑하기 위해 Selenium을 활용한 방법에 대해 알아보겠습니다. 이 포스트에서는 웹 페이지의 로딩 시간을 고려한 Wait 기법과 마우스 및 키보드 이벤트 처리 방법을 다루겠습니다.
1. Wait and Call
동적 웹사이트를 스크래핑할 때, Selenium은 페이지의 로딩 시간을 고려해야 합니다. 이를 위해 Implicit Wait과 Explicit Wait을 사용할 수 있습니다.
Implicit Wait과 Explicit Wait
- Implicit Wait: 웹 드라이버가 특정 요소를 찾기 위해 지정한 시간 동안 기다립니다. 요소가 로드되면 즉시 다음 단계로 진행합니다.
- Explicit Wait: 특정 조건이 충족될 때까지 기다립니다. 예를 들어, 특정 요소가 나타날 때까지 대기합니다.
스크래핑할 사이트: IndieStreet 이벤트
IndieStreet의 이벤트 리스트를 스크래핑하기 위해 아래의 웹사이트를 사용합니다: IndieStreet Events
1. 스크래핑에 필요한 라이브러리 불러오기
먼저, Selenium을 통해 스크래핑에 필요한 라이브러리를 불러옵니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
2. XPath 이해하기
이 웹사이트의 요소는 랜덤하게 생성된 클래스 이름을 가지고 있으므로, XPath를 사용하여 요소를 선택합니다. XPath는 HTML 문서의 요소 위치를 경로로 표현하는 방식입니다.
예시 XPath:
[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]
3. 암시적 기다림 (Implicit Wait) 적용하기
암시적 기다림을 설정하여 페이지가 로드될 때까지 대기하는 방법입니다.
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get('https://indistreet.com/live?sortOption=startDate%3AASC')
driver.implicitly_wait(10) # 10초 동안 기다림
print(driver.find_element(By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]').text)
4. 명시적 기다림 (Explicit Wait) 적용하기
특정 요소가 로드될 때까지 대기하는 방법입니다.
from selenium.webdriver.support.ui import WebDriverWait
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, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]')))
print(element.text)
5. 여러 공연 제목 가져오기
이벤트 제목을 여러 개 가져오기 위해 XPath를 일반화합니다.
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get('https://indistreet.com/live?sortOption=startDate%3AASC')
driver.implicitly_wait(10) # 10초 대기
for i in range(1, 11):
e = driver.find_element(By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[{}]/div/a/div[2]/p[1]'.format(i))
print(e.text)
출력 예시
- Knock Live Rock band
- 이디어츠 1st EP 발매기념 공연
- 도라페스트 4탄
- NO PASARAN! Vol.1
- 2019년 5월 17일 카페 아이다호 공연 - 권유 (gwon.u)
- LIVE in NOV 2019
- LIVE in DEC 2019
- Thursday Mood
- 오롯한 라이브와 함께
2. 마우스 이벤트 처리하기
Selenium을 이용해서 마우스 이벤트를 동작해봅시다.
Mouse Event
웹 페이지에서 일어나는 일들을 Event라고 합니다. 마우스로 일어날 수 있는 대표적인 이벤트는 다음과 같습니다:
- 마우스 움직이기 (move)
- 마우스 누르기 (press down)
- 마우스 떼기 (press up)
저희는 버튼을 찾은 후 이를 클릭하는 것을 목표로 합니다.
마우스 입력 과정
- 입력하고자 하는 대상 요소를 찾습니다. (
find_element()이용) - 입력하고자 하는 내용을
click을 통해 전달합니다. .perform()을 통해 동작합니다.
아래 예시는 id가 textInput인 요소를 클릭하는 예제입니다.
button = driver.find_element(By.ID, "button")
ActionChains(driver).click(button).perform()
스크래핑에 필요한 라이브러리 불러오기
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
로그인 창 접속하기
주어진 웹사이트를 누른 후, 원하는 버튼 요소를 찾아 마우스 이벤트를 실행시켜봅시다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get('https://hashcode.co.kr/')
driver.implicitly_wait(0.5)
button = driver.find_element(By.CLASS_NAME, "nav-link.nav-signin")
ActionChains(driver).click(button).perform()
3. 키보드 이벤트 처리하기
Selenium을 이용해서 키보드 이벤트를 동작해봅시다.
Keyboard Event
웹 페이지에서 일어나는 일들을 Event라고 합니다. 키보드로 일어날 수 있는 대표적인 이벤트는 다음과 같습니다:
- 키보드 누르기 (press down)
- 키보드 떼기 (press up)
저희는 입력창(input 태그의 form)에 키보드 입력을 진행하는 것을 목표로 합니다.
키보드 입력 과정
- 입력하고자 하는 대상 요소를 찾습니다. (
find_element()이용) - 입력하고자 하는 내용을
send_keys_to_element를 통해 전달합니다. .perform()을 통해 동작합니다.
아래 예시는 id가 textInput인 요소에 “abc”를 입력하는 예제입니다.
text_input = driver.find_element(By.ID, "textInput")
ActionChains(driver).send_keys_to_element(text_input, "abc").perform()
로그인 자동화 코드
이제, 로그인 과정을 자동화해봅시다.
import time
# driver를 이용해 해당 사이트에 요청을 보내봅시다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get('https://hashcode.co.kr')
time.sleep(1)
# 내비게이션 바에서 "로그인" 버튼을 찾아 눌러봅시다.
button = driver.find_element(By.CLASS_NAME, "nav-link.nav-signin")
ActionChains(driver).click(button).perform()
time.sleep(1)
# "아이디" input 요소에 여러분의 아이디를 입력합니다.
id_input = driver.find_element(By.ID, "user_email")
ActionChains(driver).send_keys_to_element(id_input, "내 아이디").perform()
time.sleep(1)
# "패스워드" input 요소에 여러분의 비밀번호를 입력합니다.
pw_input = driver.find_element(By.ID, "user_password")
ActionChains(driver).send_keys_to_element(pw_input, "내 비번").perform()
time.sleep(1)
# "로그인" 버튼을 눌러서 로그인을 완료합니다.
login_btn = driver.find_element(By.ID, "btn-sign-in")
ActionChains(driver).click(login_btn).perform()
time.sleep(1)
오류 처리
위 코드를 실행하면 다음과 같은 오류가 발생할 수 있습니다.
NoSuchElementException: Unable to locate element: {"method":"css selector","selector":".nav-link.nav-signin"}
이는 요소를 찾지 못했음을 의미합니다. 정확한 클래스를 사용했는지, 페이지가 로드된 후 요소가 렌더링되는 시간을 고려해야 합니다. 필요하다면 implicitly_wait를 조정하여 페이지가 로드될 때까지 기다리도록 설정할 수 있습니다.
결론
Selenium을 활용한 마우스 및 키보드 이벤트 처리로 해시코드 사이트에 로그인하는 과정을 자동화해 보았습니다. 이 과정을 통해 웹 페이지의 다양한 요소와 상호작용할 수 있는 방법을 익힐 수 있었습니다.
댓글남기기