*** selenium 사용하는 이유? ***
- 정적으로 데이터들 처리 ( 웹페이지에 접속 시 얻은 데이터만 처리한다 등) 그래서 자바스크립트가 들어있는 웹 페이지를 크롤링하게 되면 그 동작들을 제대로 캐치하지 못하고 경우가 생긴다. 그 외에도 웹 사이트에 마우스/키보드 입력이 있는 경우에도 제한이 생긴다.
selenium :
- html 값들을 처리함에 있어 동적으로 변하는 웹 페이지의 데이터들까지 설정하여 크롤링할 수 있다.
실제 사용자들처럼 마우스클릭, 키보드입력 등의 입력이 가능해져서 url을 통해서만 다른 페이지 접근하는게 아니라 버튼을 누르고 값을 입력하게 만들어서 값을 추출한다.
1. 설치하기
selenium을 사용하기 위해서 1) 라이브러리 설치와 2) 셀레니움용 웹드라이브를 각각 설치해야 한다!
1) 라이브러리 설치
pip install selenium
2) selenium 웹드러이버(web driver) 설치
* 각각의 브라우저마다 따르다. 크롬을 쓸 거니까 크롬 웹드라이버를 깐다.
-링크 주소 : Chrome 링크에서 다운로드 후 설치 하면된다.
본인의 크롬브라우저 버전과 일치하는 버전을 설치해야 오류가 없다!!
2. 기본
from selenium import webdriver
path ="크롬 웹드라이버 경로"
driver=webdriver.Chrome(path) #chromedriver.exe가 같은 위체에 있을 때 비어 있어도 된다.
driver.get("크롤링하려는 웹페이지 URL주소")
# 파싱할 웹 페이지 주소 입력
print(driver.title)
등등의 작업
driver.close()
* selenium을 실행하면, 웹드라이브도 옆에서 같이 실행이 된다 *
※ "usd_device_ handle_win.cc 관련 시스템에 부착된 장치가 작동하지 않습니다." 오류 발생 시 조치방법
해결 방법 : 장치 관리지 -> USB Composite Device -> 오른쪽 클릭 '디바이스 사용 안 함'
3. 웹 브라우저(크롬) 자체에 설정하기
( option 이용, .add_argument(옵션 값) )
1) selenium 실행 시 웹드라이브가 뜨지 않도록 하기
options.add_argument('headless')
2) 창 크기를 조절
options.add_argument('window-size=1920x1080')
3) 전체 화면(F11)으로 조절
options.add_argument('--start-fullscreen')
4) user-agent 설정하기
user_agent = "Mozilla/5.0 (Linux; Android 9; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.83 Mobile Safari/537.36"
#지정한 user-agent로 설정합니다.
options.add_argument('user-agent=' + user_agent)
5) 이미지를 로딩하지 않도록 설정
options.add_argument('--blink-settings=imagesEnabled=false')
6) 음소거
options.add_argument('--mute-audio')
7) 시크릿 모드로 실행하게 설정
options.add_argument('incognito')
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
옵션 설정하기
options.add_argument(설정할 옵션)
driver = webdriver.Chrome("웹드라이버 경로", chrome_options=options)
4. 원하는 요소/요소들 찾기 (find element / find elements)
- 하나의 요소만 찾을 때 : find_element
- 여러 개의 요소만 찾을 때 : find_elements
# 1 find_element _by_???? 로 요소를 찾기
????에 들어갈 수 있는 것 :
id / name / class_name / link_text / partial_link_text / tag_name / css_selector / xpath 로 값을 찾기
1) id로 접근 (여러 개 요소로 접근 불가!)
driver.find_element_by_id('insert_btn')
2) name으로 접근
driver.find_element_by_name('movie')
3) class명으로 접근
driver.find_element_by_class_name('submit')
4) 링크가 달려 있는 텍스트로 접근
driver.find_element_by_link_text('회원가입')
5) 링크가 달려 있는 엘레먼트에 텍스트 일부만 적어서 해당 엘레먼트에 접근
driver.find_element_by_partial_link_text('가입')
6) 태그 이름으로 접근
driver.find_element_by_tag_name('input')
7) css 셀렉터로 접근
driver.find_element_by_css_selector('#account > div > a')
8) xpath로 접근
driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[1]/div/div[3]/form/fieldset/button/span[2]')
//input[@id='username']
9) xpath + tag
driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[1]/div/div[3]/form/fieldset/button/span[2]').find_element_by_name('join')
#xpath 로 접근한 엘레먼트의 안에 join 이라는 속성을 가진 tag 엘레먼트에 접근
10) tag_name + tag_name
driver.find_element_by_tag_name('input').find_element_by_tag_name('a')
# 2 BY.????로 find_element 하기
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')
BY.????
????에 들어 갈 수 있는 것
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
5. 찾은 요소로 브라우저에 무엇인가 시키기
- 클릭 / 텍스트 압력과 삭제 / 드래그 앤 드롭 / 프래임으로 이동 / 탭으로 이동 / 경고창 다루기 / 쿠키값 다루기 / 자바스크립트 실행 / 화면 캡처
1) 클릭
driver.find_element_by_id('submit').click()
또는
driver.submit()
2) 텍스트 입력 / 삭제
driver.find_element_by_id('in_btn').send_keys('텍스트 입력') # 입력
driver.clear() #삭제
3) 드래그엔 드롭 * actionchains
드래그하는 것 설정
element = driver.find_element_by_name("source")
어디로 드래그할지 설정
target = driver.find_element_by_name("target")
from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()
4) 프레임으로 이동시키기
- 이동할 프레임 요소 지정
element = driver.find_element_by_tag_name('iframe')
- 이동
driver.switch_to.frame(element)
- 프레임에서 빠져나오기
driver.switch_to.default_content()
5) 탭 이동
driver.window_handles[0] #브라우저 탭 객체를 리스트로 반환. [0] 은 인덱싱. 첫 번째 탭을 의미
driver.switch_to.window(driver.window_handles[0]) #첫 번째 탭으로 이동
driver.switch_to.window(driver.window_handles[1]) #두 번째 탭으로 이동
driver.switch_to.window(driver.window_handles[2]) #세 번째 탭으로 이동
6) 경고창 다루기
- 경고창으로 이동
driver.switch_to.alert
- 경고창 수락/거절/텍스트 값 가져오기
from selenium.webdriver.common.alert import Alert
Alert(driver).accept() #경고창 수락 누름
Alert(driver).dismiss() #경고창 거절 누름
print(Alert(driver).text) # 경고창 텍스트 얻음
7) 쿠키값 처리하기
- 쿠키값 얻기
driver.get_cookies()
- 쿠키 추가
driver.add_cookie()
- 쿠키 전부 삭제
driver.delete_all_cookies()
- 특정 쿠기 삭제
driver.delete_cookie(cookiename)
8) 자바스크립트 실행시키기 (.execute_script)
- 스크롤 이동
#브라우저 스크롤 최하단으로 이동
driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
- CSS 셀렉터로 클릭
driver.execute_script("document.querySelector('body > div.modal-options__buttons > button.btn.btn-primary').click();")
- 스크롤 특정 엘리먼트로 이동
element = driver.find_element_by_css_selector('div > a')
driver.execute_script('arguments[0].scrollIntoView(true);', element)
- 새 탭 열기
driver.execute_script('window.open("https://naver.com");')
9) 화면 캡처하고 저장하기
- 캡쳐할 엘레먼트 지정
element = driver.driver.find_element_by_class_name('title_submit')
- 캡쳐
element.save_screenshot('image.png')
element.get_screenshot_as_file('<파일명>.png')
6. 행동을 다 시켰으면...?? 앞으로 가고 뒤로 가고 닫기
1) 앞으로 가기/뒤로 가기
driver.back() #뒤로 가기
driver.forward() #앞으로 가기
2) 닫기
driver.close() #현재 탭만 닫기
driver.quit() #브라우저 닫기
7. Wait (대기/기다림) 설정하기
- 무엇인가 시키기 전에 몇 초 기다리게 설정하기
요즘 대부분의 웹은 AJAX 사용한다.
그래서 웹 페이지가 실행될 때 동시에 모든 요소(element)가 한꺼번에 로드되지 않고, 필요할 때마다 필요한 요소가 따로 로드된다. 그래서 요소가 로드되는 시간이 다른다.
그 외에도 요소들이 연산을 수행하게 되면 결과가 나오기까지 시간이 좀 더 걸리게 된다.
그래서 웹페이지가 실행하자마자의 얻은 값을 이용하는 것이 아니라 몇 초간 기다려를 이런 문제를 해결할 수 있다.
AJAX( Asynchronous Javascript And XML )
- 비동기식 자바스크립트와 XML
- 자바스크립트를 이용해 서버와 브라우저가 비동기 방식으로 데이터를 교환할 수 있는 통신 기능. 브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법
기다림(Wait)에는 두 가지가 있다.
1) 명시적 대기
- 웹페이지 다 로드되기 전까지 시간을 정해서 지정한 시간을 기다리게 하는 것
> time.sleep(기다릴 시간)로 시간 설정
WebDriverWait(driver, 100).until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.header")))
2) 암묵적 대기
웹페이지에서 내가 필요한 특정 요소가 준비될 때까지 암묵적으로 최대 ~초 기다리게 하는 것
> driver.implicitly_wait(조건이 만족할 때까지 최대로 기다릴 시간)을 이용한다.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")
[ 참고 ]
https://selenium-python.readthedocs.io/index.html
https://pythondocs.net/selenium/셀레니움-크롤러-기본-사용법/