끄적거림

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 3(feat. selenium) 본문

Python/Crawling

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 3(feat. selenium)

Signing 2020. 7. 27. 15:01
728x90
반응형

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 1(feat. selenium)

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 2(feat. selenium)

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 3(feat. selenium)

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 4(feat. selenium)

[리뷰 크롤링] PlayStore 댓글 크롤링하기 in python 5(feat. selenium)

 


 

 

데이터를 가져오는 것까지는 잘 가져왔고 어떻게 가져오는지도 확인했다.

그렇다면 이제 모든 데이터를 가져와서 어떤 포멧으로 데이터를 적재할지 생각해보자.

 

 

 


 

1. 전체 리뷰 데이터에 접근하기

reviews = driver.find_elements_by_xpath("//span[@jsname='bN97Pc']")
len(reviews)

위에서 했던것에서 find_element_by_xpath 대신 find_elements_by_xpath를 사용하여 원하는 리뷰 데이터를 한 번에 가져오고자한다.

실제로 이를 실행시키면 40개의 리뷰 데이터를 가져온다.

 

잉? 분명 그럴리가 없다. 이 어플은 내가 사용한지 오래되기도 했고 플레이스토어에 접속해서 확인만하더라도 많은 리뷰데이터를 가지고 있다.

 

왜그럴까?

 

그 이유는 모든 리뷰데이터가 전부 웹페이지에 로드되지 않아서다.

 

여기에서 BeautifulSoup과 Selenium과의 차이가 발생한다고 생각한다.

BeautifulSoup은 단순 스크래핑, 즉, 화면상에 떠있는 정보에 한해서만 데이터를 가져올 수 있다.

리뷰 더보기, 전체보기 등과 같은 일부 클릭 베이스 정보는 얻을 수 없다.

 

하지만, Selenium은 다르다.

Selenium은 특정 봇을 만들 수 있을만큼 온라인상 행동을 유도할 수 있다.

즉, 사용자가 원하는 특정행동을 온라인 상에서 진행할 수 있다는 의미이다.

 

리뷰 데이터를 전부 가져오기 위해서는 리뷰 리스트의 가장 마지막까지 스크롤을 내리고 리뷰 더보기를 클릭하는등의 동작이 필요하다.

 

나는 지금부터 이 동작을을 진행해보고자 한다.

 

 

 

 

1.1) 스크롤 내리기

driver 객체에서 execute_script 함수를 사용한다.(참고 : https://pythonbasics.org/selenium-scroll-down/)

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

이 코드를 돌리면 실제로 웹브라우저의 스크롤이 맨 밑으로 향하는 것을 확인할 수 있다.

그럼 이걸 계속 뜰때가지 계속 돌려야하는건가?

아니다. 반복문을 사용하면 그럴 걱정이 없다.

그래서 다음과 같은 코드를 만들 수 있다.

for i in range(100):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
    time.sleep(2)

일단 예시로 100번만 돌리기로 하고 중간중간마다 sleep을 넣어줬다.

이렇게 하지 않으면 딜레이되는 시간에 루프가 다 돌기 때문에 의미가 없어진다.

 

그렇게해서 실행해보면...

 

안된다. 왜안될까?

 

실제로 4번정도 스크롤을 맨 밑으로 내리게되면 "더보기"라는 문구가 뜨면서 이 문구를 클릭해줘야 더 많은 리뷰를 볼 수 있다.

 

 

 

1.2) 더보기 클릭

더보기 클릭해보기

이제 이 "더보기"라는 버튼을 클릭하고자 한다.

 

 

더보기 버튼 구조

더보기 버튼을 html로 확인해보니

<span class="RveJvd snByac">더보기</span>

와 같은 구조로 이루어져 있었다.

 

더보기 버튼의 구조와 위치를 알았으니 이제 클릭을 진행해보자. 방법은 간단하다.

driver.find_element_by_xpath("//span[@class='RveJvd snByac']").click()

xpath문법을 이용하여 해당 위치를 찾은 다음, click( )함수를 이용하여 클릭을 진행하면 된다.

그러면 신기하게도 클릭이 된다!!

 

 

 

1.3) 마지막 리뷰까지...

일단 맨 끝까지 행동하는 법은 알았다. 몇 번 일련의 반복만 있으면 될 것 같다.

맨 마지막 리뷰까지 도달할 수 있는 로직을 생각해보면 아래와 같을 것이다.

수도코드로 한 번 작성해 보았다.

while True:
	(1) 4번의 스크롤링
	(2) 더보기 클릭
	if 방금 전의 Height == 지금의 Height: # 종료조건
    		break

나쁘지 않은 로직인 것 같다.

이를 토대로 코드를 짜보자

 

SCROLL_PAUSE_TIME = 1.5
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
    # (1) 4번의  스크롤링
    for i in range(4):
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(SCROLL_PAUSE_TIME)

    # (2) 더보기 클릭
    driver.find_element_by_xpath("//span[@class='RveJvd snByac']").click()
    
    # (3) 종료 조건
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

위의 코드는 실제 코드이다.

첫 번째 라인은 스크롤을 내리거나 할 때의 딜레이 시간이다. 이를 하지 않으면 에러가 나고 내 생각엔 1.5초가 경험상 괜찮았던 것 같다.

두 번째 라인은 단지 height를 알기 위한 내용이다.

그러고 무한루프를 열어서 4번의 스크롤링과 더보기 버튼 클릭을 해주고,

다시 한 번 height를 받아서 비교를 해본다.

만약 아니라면 height를 업데이트 해준다.

 

사실 종료 조건은 꼭 이것이 아니어도 된다. 실제로 해보니 과거 ZUMO 시절때까지의 리뷰도 나오는 것으로 봐서 최신순으로 정렬한 다음에 Date변수로 종료조건을 하는 것도 괜찮은 방법이라는 생각이 든다.

 

실제로 돌려보면 대단하다.. 라는 생각만 들뿐이다ㅎㅎㅎ

 

 

 

 

 

 

2. 데이터 수집하기 

원하는 부분, 혹은 날짜까지의 리뷰에 도달했다면, 이제 본격적으로 크롤링을 진행해보자.

리뷰데이터 크롤링

코드나 방법은 이미 전시간에서도 다뤘기 때문에 그대로 사용해주면 된다.

다만, 보이는 것처럼 출력하면 실제 객체와 관련된 정보만 출력되고, 각 element들에 접근하고 이를 text로 해주어야 원하는 텍스트 데이터를 얻을 수 있다.

리뷰 뿐 아니라 다른 정보들도 마찬가지이다.

 

이 각각의 데이터를 루프를 돌려 각각 원소에 접근하여 dictionary로 만들어서 append하는 방향으로 진행해보자.

res_dict = []
for i in range(len(reviews)):
    res_dict.append({
        'DATE' : dates[i].text,
        'STAR' : stars[i].get_attribute('aria-label'),
        'LIKE' : likes[i].text,
        'REVIEW' : reviews[i].text
    })
    
res_df = pd.DataFrame(res_dict)
res_df

모든 루프를 돌고 거기다가 append작업까지 있어서, (append가 어떻게 작동되는지는 확실하지 않으나) 대략 O(n^2)만큼의 시간이 소요되는 것으로 생각이든다.

리뷰의 갯수가 더 많아질수록 더 오래걸리기도 한다.

(이거 개선할 수 있는 방법 아시는 분은 댓글로..ㅎㅎ)

 

 

어쨌든 내가 그토록 원하던 데이터를 얻을 수 있었다.

 

 

 

 

 

 

 

 

728x90
반응형
Comments