본문 바로가기
TOP
데이터 스킬업/웹크롤링

[ep01:웹크롤링] #16 셀레니움 스크롤 조절하기 with 파이썬

by 티챠림 2021. 8. 3.

[왕초보 웹크롤링 따라하기] 웹 제어, 브라우저 크기 설정, 셀레니움, Selenium, 스크롤 내리기, 스크롤 끝까지 내리기, 스크롤 위치 확인, 스크롤 단계별 내리기


업무지옥을 탈출한 건에 대하여(feat.업무자동화) 

#16 인스타그램 로그인하기(브라우저 크기 설정/셀레니움)


스크롤 내리기 반복문 (바로가기 Click)

인스타그램 피드 전체 마우스 오버하기 (바로가기 Click)


이제 스크롤을 제어할 차례다. 이 것만 익힌다면 브라우저에서 할 수 있는 동작은 대부분 익힌 것이나 다름없다.

이전 스크롤을 지정 위치까지 내리는 것은 해봤으니 단계적으로 내리거나 끝까지 내리는 방법을 알아보자. 스크롤을 움직이는데 필요한 자바스크립 코드는 특별할 게 없다. 단지 반복문을 사용할 뿐이다.

 

# 현재 스크롤 전체 길이 추출 
dr.execute_script("return document.body.scrollHeight") 

# 현재 스크롤 좌표 추출 
dr.execute_script("return window.pageYOffset") 

# 지정 좌표로 스크롤 이동 
dr.execute_script("window.scrollTo(0, 0)")

 

 


스크롤 내리기 반복문


스크롤이 더이상 늘어나지 않을 때까지 내리는 반복문은 간단하다. 스크롤을 가장 아래까지 내렸다가 스크롤 전체 높이가 추가되면, 또 다시 가장 아래까지 내리기를 반복하면 된다. 스크롤의 전체 높이는 dr.execute_script("return document.body.scrollHeight")로 구할 수 있다. 이를 동작이 참일 때 반복하는 while True: if문을 사용해 반복문을 만들면 아래와 같다.

 

▼스크롤 끝까지 내리기 반복문

#스크롤 내리기 이동 전 위치
scroll_location = dr.execute_script("return document.body.scrollHeight")

while True:
	#현재 스크롤의 가장 아래로 내림
    dr.execute_script("window.scrollTo(0,document.body.scrollHeight)")
       
    #전체 스크롤이 늘어날 때까지 대기
    time.sleep(2)
    
    #늘어난 스크롤 높이
    scroll_height = dr.execute_script("return document.body.scrollHeight")

    #늘어난 스크롤 위치와 이동 전 위치 같으면(더 이상 스크롤이 늘어나지 않으면) 종료
    if scroll_location == scroll_height:
    	break
	    
    #같지 않으면 스크롤 위치 값을 수정하여 같아질 때까지 반복
    else:
    	#스크롤 위치값을 수정
    	scroll_location = dr.execute_script("return document.body.scrollHeight")

 

 


 

이를 응용해서 일정 구간 씩 내리는 것도 가능하다. 스크롤을 끝까지 내릴때는 스크롤 전체 높이를 기준으로 사용했지만, 일정 구간 씩 내릴 땐 현재 스크롤 위치를 기준으로 한다. 현재 스크롤 위치는  dr.execute_script("return window.pageYOffset")로 확인할 수 있다. 반복문에서 스크롤 내리는 길이를 현재 위치 + 500으로 설정하면 500씩 단계적으로 내려가게 할 수 있다. '현재 위치 + 500'을 만들기 위해서는 format을 사용해준다.

 

▼ 스크롤 500씩 내리는 반복문 코드

#이동 전 스크롤 위치
before_location = dr.execute_script("return window.pageYOffset")

while True:
	#현재 위치 + 500으로 스크롤 이동
    dr.execute_script("window.scrollTo(0,{})".format(scroll_location + 500))
        
    #전체 스크롤이 늘어날 때까지 대기
    time.sleep(2)
    
    #이동 후 스크롤 위치
    after_location = dr.execute_script("return window.pageYOffset")
    
    #이동후 위치와 이동 후 위치가 같으면(더 이상 스크롤이 늘어나지 않으면) 종료
    if before_location == after_location:
    	break

    #같지 않으면 다음 조건 실행
    else:
        #이동여부 판단 기준이 되는 이전 위치 값 수정
        before_location = dr.execute_script("return window.pageYOffset")

 

 


인스타그램 피드 전체 마우스 오버하기


상대좌표 마우스오버 코드에 스크롤 제어 반복문까지 더하면 이제 모든 피드의 데이터를 크롤링할 수 있다. 그런데 반복문을 합치는 것인 꽤나 골치 아픈일이다. 반복문은 복잡할 수록 오류가 늘고 어디가 문제인지 확인하기 어렵기 때문이다. 일단 만들어 둔 크롤링 코드와 스크롤 제어코드를 단순하게 섞어서 실험해 보기로 했다.

 

▼ 상대좌표로 브라우저상 피드 12개 마우스 오버 하기 

 

[ep01:웹크롤링] #15 셀레니움 절대좌표/상대좌표 활용하기 with 파이썬

[왕초보 웹크롤링 무작정 따라하기] 웹크롤링, 셀레니움, 절대좌표, 상대좌표, 요소위치 확인, 자바스크립트 사용 업무지옥을 탈출한 건에 대하여(feat.업무자동화) #15 셀레니움 절대좌표/상대

charimlab.tistory.com

dr.execute_script("window.scrollTo(0, 492)")
standard_logo = dr.find_element_by_xpath('//section/nav/div[2]/div/div/div[1]/a/div/div')

for line in range(0, 4):  
    y = 110 + 175 * line  
    for box in range(0, 3):  
        x = 175 * box  
        act = ActionChains(dr)
        act.move_to_element(standard_logo).move_by_offset(x, y).perform()

 

▼ 스크롤 500씩 내리는 반복문 코드

scroll_location = dr.execute_script("return window.pageYOffset")

while True:
    scroll_height = dr.execute_script("return document.body.scrollHeight")
    if scroll_location == scroll_height:
    	break
    else:
    	dr.execute_script("window.scrollTo(0,{})".format(scroll_location + 500))
        time.sleep(2)
        scroll_location = dr.execute_script("return window.pageYOffset")

 


 

반복문 코드를 합칠 때 헤깔리는 부분이 '어떤 코드를 먼저 수행하게 할 것인가'다. 이번에는 마우스 오버 후 스크롤 내리는 행동을 반복해야 하기 때문에, 마우스 오버 코드 다음에 스크롤 이동 코드를 두었다. 이후 새로운 12개 피드가 나오도록 스크롤을 내려도록 만들면 된다. 스크롤 간격을 확인하기 위해 1번째 피드와 13번째 피드의 좌표값을 구해 빼주니 648이 나왔다.

 

▼ 브라우저 상에서 보이는 12개 피드를 바우스 오버하고, 이후 스크롤을 648만큼 내리는 반복문

dr.execute_script("window.scrollTo(0, 492)")
scroll_location = dr.execute_script("return window.pageYOffset")

while True:
    # 상대좌표 마우스 오버 코드
    standard_logo = dr.find_element_by_xpath('//section/nav/div[2]/div/div/div[1]/a/div/div')
    for line in range(0, 4):
        y = 110 + 175 * line
        for box in range(0, 3):
            x = 175 * box
            act = ActionChains(dr)
            # 로고 좌표에 상대좌표를 더해 피드 마우스 오버
            act.move_to_element(standard_logo).move_by_offset(x, y).perform()
            
	#스크롤 구간 내리기 코드
    dr.execute_script("window.scrollTo(0,{})".format(scroll_location + 649))
    time.sleep(2)
    scroll_height = dr.execute_script("return window.pageYOffset")

    if scroll_location == scroll_height:
        break

    else:
        scroll_location = dr.execute_script("return window.pageYOffset")

 

인스타그램 피드 전체를 크롤링하기 위한 동작 제어는 끝났다. 그런데 스크롤을 내리고 2초 기다리는게 영 답답하다. time.sleep을 안주자니 로딩 오류가 날 것 같고. 타임슬립을 대신해서 로딩이 되거나 특정 조건을 만족할 때 다음 동작을 실행하는 방법을 알아보자!

 

- 계속 -

 


[system]

주문 중첩을 성공하였습니다.

'스킬 : 주문중첩' 획득

 

'스킬 : 동작 제어'를 습득률: 100%

'스킬: 동작 제어' 획득

 


[보유 스킬]

동작제어, 자바스크립트 활용,

주문중첩, 주문연계, 

데이터시각화, 데이터필터링, 웹데이터 소환

 

[보유 칭호]

브라우저를 제어하는 자, 웹데이터를 불러내는 자


 

댓글