본문 바로가기
국비 교육/데이터

[데이터 수집] 셀레니움 -1

by 육츠 2023. 11. 1.
Contents 접기

BeautifulSoup = 자바스크립트를 사용하여 동적으로 생성된 정보는 가져올 수 없다.

 

동적 홈페이지를 활용하기 위해서 사용하는 패키지

Selenium

- URL만으로 접근할 수 없는 홈페이지에 접근
- 크롤링이 목적 아닌 만들어진 홈페이지를 테스트하고 웹 브라우저를 제어할 목적으로 사용된다
- 브라우저를 직접 제어하여 사이트의 다양한 HTML 요소에 클릭, 키보드 입력 등 이벤트 처리를 할 수 있다.

-  웹 드라이저로 브라우저를 직접 띄우고 제어하여 상대적으로 로딩이 오래 걸림
- 따라서 time 모듈의 sleep 함수와 함께 조금씩 시간차를 두고 실행하는 것이 좋다.

 

패키지 설치 방법

# 아나콘다 프롬프트
pip install selenium
pip install webdriver_manager

# 아나콘다 노트북 
!pip install selenium
!pip install webdriver_manager

 

Webdriver 사용

2가지 방식이 존재한다.

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

# 1. 웹드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options = webdriver.ChromeOptions())

# 2. 기 설치돤 웹 드라이버 구동 방식
s = Service(r'c:\DEV\chromedriver\chromedriver.exe') #설치된 웹 드라이버의 경로 지정
driver = webdriver.Chrome(service = s)

 

HTML 정보읽기

- find_elements(): find_all()과 유사하다. 해당하는 조건 모두 검색하여 리스트로 반환
- find_element(): find()와 유사하다. 해당 하는 조건중 가장 먼저 검색된 것 선택

- by 속성: 검색 기준 지정
-value 속성: 태그 이름 지정

By.ID : 태그의 id값으로 추출 By.XPATH: 태그의 경로로 추출(select()와 유사) By.TAG_NAME: 태그 이름으로 추출 By.CLASS_NAME: 태그 클래스 이름으로 추출
By.NAME: 태그의 from name 값으로 추출 By.LINK_TEXT: 링크 텍스트값으로 추출 By.CSS_SLSCTOR: css 선택자로 추출  

이벤트 제어(대표적 3개)

click():  마우스 클릭 send_keys(): 키보드 입력 excute_script(): 자바스크리트 삽입
# find_element()함수

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

# 웹드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options = webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(by=By.LINK_TEXT,value='카페') 
# 다음 홈페이지에서 링크에 있는 카페라는 단어의 정보를 찾음

print(ele)
# <selenium.webdriver.remote.webelement.WebElement (session="52fd3aac76b4add2674149c409cbbbe8", element="B6968CF2274E93EA6D82D664D4228D47_element_23")>
# 따로 태그가 나오는 것은 아니다.
print(type(ele))
print(ele.text)


# Click()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options = webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(by=By.LINK_TEXT,value='카페')
ele.click()

# send_keys()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options = webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(By.ID,'q') # 고유한 id가 'q'
ele.send_keys('python')
ele.send_keys(Keys.ENTER) # 특수문자

 

BeautifulSoup 과 연결하기

bs = BeautifulSoup(driver.page_source,'lxml')
m = BeautifulSoup(res,'lxml')와 유사한 형식. (driver.page : drivermanager 를 통해 동적 페이지를 얻어온 것)

 


[실습] 네이버 로그인하기


필요한 패키지 호출
id = 'Myid', pw = 'Mypwd' 를 변수로 설정해 놓아 입력할 수 있는 상태로 만든다. (개인정보 보호를 위해 변경)

By.ID  활용하여 태그를 검색하였다.

<input type="text" id="id" name="id" placeholder="아이디" title="아이디" class="input_text" maxlength="41" value="">
<input type="password" id="pw" name="pw" placeholder="비밀번호" title="비밀번호" class="input_text" maxlength="16">

로그인버튼 활용하고 + 이벤트 click() 사용
<button type="submit" class="btn_login" id="log.login"><span class="btn_text">로그인</span></button>

 

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options = webdriver.ChromeOptions())

driver.get('https://www.naver.com')
ele = driver.find_element(By.CLASS_NAME,'MyView-module__link_login___HpHMW')
ele.click() # 간혹 클릭 이벤트가 적용되지 않는 경우에는 send_keys(Keys.ENTER) 를 이용하면 됨

id = 'Myid'
pw = 'Mypwd'

ele = driver.find_element(By.ID,'id')
ele.send_keys(id)

ele = driver.find_element(By.ID,'pw')
ele.send_keys(pw)

ele = driver.find_element(By.CLASS_NAME,'btn_login')
ele.click()

 

코드를 실행시키면 로봇으로 인식하게 되어 해당 로봇이 아닌지 확인하는 프로그램을 실행하게 된다.

 

그것을 해결하기 위해 자바스크립트로 작성.

excutr_script: 자바스크리트 삽입

driver.execute_script(f"document.getElementById('id').value = '{id}'")

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options = webdriver.ChromeOptions())

driver.get('https://www.naver.com')
ele = driver.find_element(By.CLASS_NAME,'MyView-module__link_login___HpHMW')
ele.click() # 간혹 클릭 이벤트가 적용되지 않는 경우에는 send_keys(Keys.ENTER) 를 이용하면 됨

id = 'Myid'
pw = 'Mypwd'

# 로봇에 의해 클릭되지 못 하도록 막았기 때문에 자바스크립트로 처리하여 로그인함
driver.execute_script(f"document.getElementById('id').value = '{id}'")
driver.execute_script(f"document.getElementById('pw').value = '{pw}'")

ele = driver.find_element(By.CLASS_NAME,'btn_login')
ele.click()

자바 스크립트를 활용하여 정상적으로 로그인 되었다.