from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
driver = webdriver.Chrome(options= chrome_options, service=Service(ChromeDriverManager().install()))
driver.get("http://url.com")
driver.implicitly_wait(1)
셀레니움을 활용한 크롤링의 기본 형태는 위 와 같다.
위 코드에서는 Chrome을 쓰고 있지만, 관공서나 정부 프로젝트로 크롤링을 원한다면 Edge를 사용하는걸 권장한다. (우리 같은 개발자야 크롬을 거의 필수처럼 쓰고있지만 다른곳은 그렇지 않다.)
셀레니움에서 크롤링을 지원하는 브라우저는 다음과 같다.
지원하고자하는 브라우저를 선택했다면 Option과 드라이버를 선택해주면 된다.
크롤링으로 사용 할 브라우저의 옵션을 정한다.
많은 옵션이 존재하지만 자주쓰는 것만 작성 해볼까한다.
options.page_load_strategy = 'normal'
options.accept_insecure_certs = False
False가 기본이며, 안전하지 않은 인증 및 세션이 있을 경우 오류를 반환한다.
안전하지 않은 인증 및 세션 검사를 무시 하고 싶을경우엔 True로 바꿔준다.
options.script_timeout(30000)
options.page_load_timeout(300000)
options.implicit_wait_timeout(0)
options.headless = False
False가 기본이며, 브라우저창을 띄운다.
True시 브라우저창을 띄우지 않고 크롤링이 실행된다.
options.add_argument("window-size=1920x1080")
options.add_argument("disable-gpu")
options.add_argument("start-fullscreen")
options.add_argument("disable-dev-shm-usage")
options.add_argument("no-sandbox")
options.add_argument("lang=ko") # 한국어
options.add_experimental_option('prefs',{'download.default_directory':r'C:\python' //다운로드 기본 경로 변경
,'download.prompt_for_download': False //prompt 창 띄울지 여부
,'donwload.directory_upgrade':True //경로 업그레이드 여부
,'safebrowsing.enabled':True //안전한 파일만 다운할지 여부
})
options.add_argument('headless')
options.add_argument('no-sandbox') # 크롬일 경우
options.add_argument('disable-dev-shm-usage')
셀레니움으로 제어하는 법을 알아 보자.
스코프 크기를 기준으로
1. browser
2. window
3. dom(frame)
4. wait
5. script
순으로 진행하겠다.
URL = 'https://www.selenium.dev/ko/documentation/'
options = Options()
driver = webdriver.Chrome(options= chrome_options, service=Service(ChromeDriverManager().install()))
driver.get(url=URL)
핵심은 driver.get(url=)
을 통해 원하는 url을 불러 올 수 있다는 점이다.
print(driver.current_url)
dirver.quit()
브라우저를 닫음과 동시에 크롤링을 종료한다는 의미이기도 하다.
브라우저안에서 여러 창을 띄워 사용 할 때도 있다. ( ex : 팝업창, Tab )
for item in driver.window_handles:
print(item)
driver.window_handles[0] # 스택 형태로 쌓이기 때문에 0번째 인덱스는 맨 처음 윈도우
driver.window_handles[-1] # 새로운 창
driver.swich_to.window(drvier.window_handles[-1]) # 새창으로 포커스 이동
driver.close()
현재 포커스하고 있는 창을 닫는다.
driver.find_element(by=By.CSS_SELECTOR, value="#trigger1") # id가 trigger1 요소 선택
driver.find_elements(by=By.CSS_SELECTOR, value="#trigger1>div") # id가 trigger1인 하위 div요소들을 선택
나는 요소 검색 방법으로 css_selector가 편해서 위 처럼 많이 쓰지만,
다른 방법도 많다 xpath, class_name등등 원하는 걸로 하자.
만약 요소에 이벤트를 발생 하고 싶다면 다음과 같이 진행하면 된다.
search_box = driver.find_element(by=By.CSS_SELECTOR, value="#trigger1")
search_box.send_keys('artlogy.github.io')
search_box = driver.find_element(by=By.CSS_SELECTOR, value="input[type=file]")
upload.send_keys(file_path)
파일을 업로드 할 수 있는 input요소를 선택한 후 업로드 할 file_path를 넣어주면 된다.
from selenium.webdriver.common.keys import Keys
search_box = driver.find_element(by=By.CSS_SELECTOR, value="#trigger1")
search_box.send_keys(Keys.ENTER)
search_box = driver.find_element(by=By.CSS_SELECTOR, value="#trigger1")
search_box.click() # 클릭이벤트
search_box.submit() # 제출
search_box.clear() # input clear
from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(source, target).perform() #source요소를 target요소로 drag and drop
좀 더 세밀한 이벤트가 필요하다면 ActionChains를 사용하면 된다.
요샌 잘 안쓰지만 옛날 웹이나 정부사이트는 frame단위로 구분 된 것이 많다.
frame안에 요소를 선택 할려면 해당 frame으로 스위칭이 필요하다.
driver.switch_to.frame("fameName")
여기서 프레임이름은 해당 프레임의 ID를 넣으면된다.
driver.switch_to.default_content() # 최상위 프레임으로
driver.switch_to.parent_frame() # 상위 프레임으로 바꾸고 싶을 경우
하위 프레임을 사용하고 다시 돌아가고 싶을땐 위 코드를 이용하면 된다.
Option 파트에서도 다뤘지만, 페이지마다 로드시간이 다르고 요소마다 로드시간이 다르기 때문에
원하는 오브젝트가 로드 될 때까지 wait를 걸어주는 것도 매우 중요하다.
wait_till_load_webpage(웹페이지로딩대기)은 options에서 정하는거니 제외하겠다.
driver.implicitly_wait(time_to_wait=0)
페이지 이동, url의 앤드포인트가 변경되는 명령을 줬을 때
다음 작업(페이지 요소)가 넘어 올때까지 기다리는 최대 시간이다.
default는 0초며, 만약 10초로 설정했어도 1초만에 로드가 된다면 기다리지 않고 진행한다.
WebDriverWait(driver,0).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#txppIframe')))
implicitly_waits로 모든 것이 해결되면 좋겠지만, 요즘 웹페이지는 사용자와의 상호작용에 따라 나타나는 동적 요소도 존재하기 때문에 Explicitly_waits로 해당 요소를 명시하여 기다리는 기능 또한 필요하다.
import time
time.sleep(5)
쓰다보면 implicitly_waits, Explicitly_waits 둘다 완벽하지 않다는 걸 깨닫는다.
그땐 최후의 보루로 time.sleep()을 쓰면 좋다. 물론 무조건적인 대기를 하기 때문에, 크롤링 속도에 지대한 영향을 미치므로 최대한 자제하면서 필요한 곳에만 쓰자.
driver.execute_scripts('window.scrollTo(0, document.body.scrollHeight);')
driver.execute_script
로 js코드를 실행 할 수 있다.
위 코드는 스크롤을 맨 아래로 내리는 코드이다.
driver.back()
driver.forward()
driver.minimize_window()
driver.maxmize_window()
driver.save_screenshot("screenshotName.png")
from selenium.webdriver.common.alert import Alert
Alert(driver).accept() #확인
Alert(driver).dismiss() #취소
print(Alert(driver).text) #경고창 내용
Alert(driver).send_keys(keysToSend=Keys.ESCAPE) #경고창 무시
cookie = {"name":"foo", "value":"bar"}
driver.add_cookie(cookie)
cookies = driver.get_cookies()