본문 바로가기
내마음대로만들어보자/참고자료

[참고내용] selenium 스크롤하기

by 소농민! 2021. 6. 7.
728x90

Python 의 selenium 을 이용해서 스크롤 하기

 

크롤링 할 때 웹페이지를 스크롤 다운해야하는 경우가 있죠.

스크롤다운해서 끝까지 가야 그 다음 데이터를 조회하는 경우가 있고 그 외에도 필요한 경우가 있습니다.

 

방법 1. scrollTo

driver.execute_script("window.scrollTo(0, Y)") 

여기서 Y 는 height 을 입력하면 됩니다.

페이지 끝까지 가려면 document.body.scrollHeight 를 사용합니다.

 

 

계속해서 스크롤 다운하면서 데이터를 다 조회할때는

SCROLL_PAUSE_SEC = 1

# 스크롤 높이 가져옴
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # 끝까지 스크롤 다운
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # 1초 대기
    time.sleep(SCROLL_PAUSE_SEC)

    # 스크롤 다운 후 스크롤 높이 다시 가져옴
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

이 코드도 약간 문제가 있을 수 있는게, 로딩이 길게 걸릴땐 중간에 멈출수 있다는거죠.

이에대한 해결 방법은
1. SCROLL_PAUSE_SEC 을 늘리거나,
2. new_height 와 last_height 가 같을 때만 한번 더 sleep 하고 new_height 를 다시 가져와서 체크.

2번 방법이 나을듯합니다. 1번은 전체 크롤링 속도가 늦어질거니까요.

 

방법 2. ActionChains 의 move_to_element

이것은 특정한  element 를 알고 있을 때 그 위치까지 scroll 하게 됩니다.

예를들어 

# ActionChains 를 사용하기 위해서.
from selenium.webdriver import ActionChains

# id가 something 인 element 를 찾음
some_tag = driver.find_element_by_id('something')

# somthing element 까지 스크롤
action = ActionChains(driver)
action.move_to_element(some_tag).perform()

 코드에 'something' element를 찾았는지 체크를 하는게 좋겠습니다. if 문 하나 추가하시면 됩니다.

 

방법 3. 특정 시간동안 계속해서 scroll down 하기.

제가 사용하는 소스코드인데요. 

아래와 같이 datetime 을 이용해서 정해진 초 동안 1초에 한번씩 스크롤 다운합니다.
이 방법은 무한로딩 데이터를 다 가져올 수 없으니 적당히 가져올때 사용합니다.

    import datetime
    
    def doScrollDown(whileSeconds):
        start = datetime.datetime.now()
        end = start + datetime.timedelta(seconds=whileSeconds)
        while True:
            driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
            time.sleep(1)
            if datetime.datetime.now() > end:
                break

예를들어 60초 동안 계속해서 스크롤 다운하려면 doScrollDown(60) 이렇게 쓰면 되겠네요.
1초에 한번씩 스크롤할 필요없으면 sleep 시간을 조정하면 됩니다.

 

 

크롤링 하려는 페이지에 특성에 맞게 scroll 하면서 데이터를 다 찾아내면 되겠습니다.

 

 

무한 스크롤

# 무한 스크롤

import time

 

SCROLL_PAUSE_TIME = 2

# Get scroll height

last_height = driver.execute_script("return document.body.scrollHeight") [1]

      while True:

       # Scroll down to bottom [2]

       driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

 

# Wait to load page

time.sleep(SCROLL_PAUSE_TIME) [3]

driver.execute_script("window.scrollTo(0, document.body.scrollHeight-50);") [4] time.sleep(SCROLL_PAUSE_TIME)

 

# Calculate new scroll height and compare with last scroll height [5]

new_height = driver.execute_script("return document.body.scrollHeight")

if new_height == last_height: [6]

    break last_height = new_height

 

[ 1 ] : 마지막 시점의 창 높이 저장
[ 2 ] : 창 높이까지 스크롤
[ 3 ] : 스크롤 후 창이 로딩될때까지 2초를 기다리겠다는 명령어. 로딩이 다되면 바로 넘어감
[ 4 ] : 한 번에 맨 마지막까지 스크롤되면 아래 리스트가 뜨지 않아서, 마지막을 찍고 조금 창을 올리는 방법으로 리스트가 로딩될 수 있게 함
[ 5 ] : 스크롤이 된 후의 창 높이를 새로운 높이로 저장
[ 6 ] : 새로운 높이가 이전 높이와 변하지 않았으면 스크롤 종료