개발 기록장

04. 파이썬으로 웹 데이터를 크롤하고 분석하기(4) 본문

데브코스(DE)/파이썬으로 웹 크롤링 및 분석

04. 파이썬으로 웹 데이터를 크롤하고 분석하기(4)

jxwxnk 2024. 4. 4. 16:11
반응형
학습 주제:  Selenium, Wait and Call, 마우스/키보드 이벤트 처리, Jupyter Lab

Selenium

: 브라우저 자동화 

  • Selenium 설치
%pip install selenium

 

  • Web Driver

         - 웹 브라우저를 제어할 수 있는 자동화 프레임워크.

%pip install webdriver-manager

 

  • Selenium 시작
# selenium으로부터 webdriver 모듈 불러오기

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

#크롬 실행 및 요청 보내기
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get('http://www.example.com')
#page_source 속성 확인
print(driver.page_source)

 

  • with - as

         - Chrome 창 계속 켜져 있는 것 방지

         - 주어진 명령이 끝나면 driver 종료

 

  • Driver에서 특정 요소 추출
  • 요소 하나 찾기

         - find_element(by, target)

               by: 대상을 찾는 기준: ID, TAG_NAME, CLASS_NAME, ...

               target: 대상의 속성

#By import
from selenium.webdriver.common.by import By

# p 태그 요소 하나 찾기
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
    driver.get('http://www.example.com')
    print(driver.find_element(By.TAG_NAME, "p" ).text)

 

  • 요소 여러개 찾기

         - find_elements(by, target)

               by: 대상을 찾는 기준: ID, TAG_NAME, CLASS_NAME, ...

               target: 대상의 속성

 


Wait and Call 

: 동적 웹 사이트의 지연 시간 문제를 해결하면서, 스크래핑 진행

  • Implicit Wait vs. Explicit Wait

         - Implicit Wait(암묵적 기다림): 특정 요소에 대한 제약을 통한 기다림

                                                          ex) 5초동안 기다려 하지만, 그 전에 렌더링이 다 되면 그냥 진행해.

         - Explicit Wait(명시적 기다림): 로딩이 완료될 때까지 지정한 시간 동안 기다림

                                                         ex) 로딩이 완료될 때까지, 5초동안 기다려.

 

  • XPath

         - XML, HTML 문서 등의 요소 위치를 경로로 표현하는 것.

         - 스크래핑 방지를 위해 생성한 랜덤 class이름에 대응하여, 위치를 활용함.

         - Chrom에서 요소 Xpath 얻는 법: ctrl -> 검사 -> 해당 요소 ctrl -> copy -> copy Xpath

         - ex) //*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]

 

# 스크래핑에 필요한 라이브러리 불러오기
from selenium import webdriver
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://indistreet.com/live?sortOption=startDate%3AASC')
driver.find_element(By.XPATH,'//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]').text

 

  • Implicit Wait

         - .implicitly_wait(): 암시적 기다림 함수

         - 반드시 정해진 시간을 기다리는 것 X -> 로딩 완료될 때까지의 한계 시간 

# 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) #일단 10초를 기다리는데 그 전에 렌더링이 끝나면 넘어감
    print(driver.find_element(By.XPATH,'//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]').text)

 

  • Explicit Wait

         - WebDriverWait(): 

                        until(): 인자의 조건이 만족될 때까지

                        until_not(): 인자의 조건이 만족되지 않을 때까지

# 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')
    # explicit wait로 변경
    element=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]')))

    print(element.text)

 

  • 여러 공연 제목 가져오기

         - 여러 공연 제목에 해당하는 XPath:

                //*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[1]/div/a/div[2]/p[1]

               //*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]

               //*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[3]/div/a/div[2]/p[1]

# 10개의 제목 스크래핑
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
    	#format 함수로 인자 변경 
        element = 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(element.text)

 


마우스 이벤트 처리하기

: 로그인 과정 자동화 - '로그인' 창 접속하기

: 로그인 버튼 누르기

  • Mouse Event

         - 마우스 움직이기(move)

         - 마우스 누르기(press down)

         - 마우스 떼기(press up) 등...

 

  • 로그인 창 접속

         1. find_element(): 입력하고자 하는 대상 찾기

         2. click: 입력하고자 하는 내용 전달 

         3. .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)

#Xpath(위치)로 로그인 버튼 요소 찾기 및 마우스 이벤트 실행
button = driver.find_element(By.XPATH, '//*[@id="main-app-header"]/header/section/div/div/div/a[1]')
ActionChains(driver).click(button).perform()

키보드 이벤트 처리하기

: 로그인 과정 자동화 - '아이디, 비밀번호' 입력하기

: input 태그의 form에 키보드 입력

  • Keyboard Event

         - 키보드 누르기(press down)

         - 키보드 떼기(press up) 등...

     

  • 아이디/비밀번호 입력

         1. find_element(): 입력하고자 하는 대상 찾기

         2. send_keys_to_element: 입력하고자 하는 내용 입력

         3. .perform(): 동작 발생

# 스크래핑에 필요한 라이브러리를 불러오기
from selenium import webdriver
from selenium.webdriver import ActionChains
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

# driver를 이용해 해당 사이트에 요청을 보내봅시다.
import time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://hashcode.co.kr")
time.sleep(1) #지연시간
                          
# 내비게이션 바에서 "로그인" 버튼 누르기
button = driver.find_element(By.XPATH, '//*[@id="main-app-header"]/header/section/div/div/div/a[1]')
ActionChains(driver).click(button).perform()
time.sleep(1)

# "아이디" input 요소에 아이디 입력
id_input = driver.find_element(By.XPATH,'//*[@id="main-app-account"]/div/div[2]/div/div[2]/div[1]/div/div[2]/div[2]/input')
ActionChains(driver).send_keys_to_element(id_input,"내 아이디").perform
time.sleep(1)

# "패스워드" input 요소에 비밀번호 입력
pw_input = driver.find_element(By.XPATH,'//*[@id="main-app-account"]/div/div[2]/div/div[2]/div[1]/div/div[2]/div[4]/input')
ActionChains(driver).send_keys_to_element(pw_input,"내 비밀번호").perform
time.sleep(1)

# "로그인" 버튼을 눌러 로그인 완료
loginbutton = driver.find_element(By.XPATH,'//*[@id="main-app-account"]/div/div[2]/div/div[2]/div[1]/div/div[2]/button')
ActionChains(driver).click(loginbutton).perform()
time.sleep(1)

 

  • implicity vs. time sleep         

         - implicity: 로딩 기다리다가 중간에 완료되면 넘어감(한계 시간)

         - time sleep: 지정된 시간을 반드시 기다림


Jupyter Lab

: Interactive한 Python 코드 작성 및 공유를 위한 개발 도구

  • Jupyter Lab 설치
pip install jupyterlab

 

  • Jupyter Lab 조작법
  • Jupyter Lab Mode         

         - ESC: 명령모드

         - Enter: 입력모드

 

  • 노트북 파일 2가지      

         - Y: Code Cell

         - M: Markdown Cell

 

  • Cell 추가     

         - A(bove): 현재 Cell 위에 새로운 Cell 추가

         - B(elow): 현재 Cell 아래에 새로운 Cell 추가

 

  • Cell 삭제     

         - dd: 현재 Cell 삭제

 

  • Cell 실행     

         - ctrl/cmd + Enter: 현재 Cell 실행

 

  • Markdown

              1. Header(#, ##, ###, ...): 제목, 소제목

              2. Italic(*...*, _..._ ): 기울임체

              3. Bold(**...**, __...__): 볼드체

              4. Strikethrough(~...~): 취소선

              5. Unordered List(-..., *...): 순서 없는 리스트

              6. Ordered List(1. ..., 2. ...): 순서 있는 리스트

              7. Code(`...`): 코드 삽입

              8. Code Block(```...```): 코드 블록 삽입

 


 

공부하며 느낀점

 

Selenium을 통해 로그인을 진행할 수 있다는게 놀라웠다. 이를 응용하면 더 많은 것을 할 수 있을 것 같다. 또 평소 Jupyter Lab을 마우스로만 사용해서 조금 불편했는데, 단축키를 학습하게 되어 편리하다.
반응형