Google Playstore 크롤링
Google Playstore에서 어플을 검색해, 리뷰를 크롤링
1. 개요
아래의 스크린샷을 보면 q = {배달의 민족} 으로 입력한 검색어가 들어간 꼴이다.
즉, 사용자에게 검색할 어플명을 입력받아 q = {keyword}로 주면 해당 검색어를 입력한 것처럼 이동할 수 있다.
검색한 페이지에서 어플이름 혹은 아래의 파란 영역을 클릭하면 상세페이지로 이동한다.
그리고 이동한 페이지에서 평가 및 리뷰 옆 화살표를 클릭하면 리뷰들을 스크롤해서 전부 볼 수 있다.
아래가 화살표를 클릭했을 때 나오는 페이지.
파란색으로 보이는 영역에서, "작성자명, 작성일, 평점, 내용, 몇명에게 도움이 되었나" 정보를 가져온다.
2. 기본 창 이동
브라우저를 플레이스토어로 이동한다.
검색어를 주고 검색화면을 띄우게 한다.
검색결과 화면에서 '배달의 민족' 어플이 있는 컴포넌트를 클릭하게 한다.
#google playstore
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
#검색어 입력, 브라우저 이동
keyword = input('Enter App Service Name : ')
url = f'https://play.google.com/store/search?q={keyword}&c=apps'
browser.get(url)
#배달의 민족 컴포넌트 클릭 - 위 사진의 빨간색 네모 참고
url = browser.find_element(By.CLASS_NAME,'Qfxief').get_attribute('href')
browser.get(url)
3. 리뷰창 열기 (화살표 클릭)
버튼 class= VfPpkd-Bz112c-LgbsSe 를 찾아서 클릭
browser.find_elements(By.CLASS_NAME,'VfPpkd-Bz112c-LgbsSe').click()
하지만 위 코드를 실행했을 때 리뷰창이 열리지 않았다.
그 이유는, 해당 클래스의 이름을 가진 버튼이 하나가 아니기 때문이다.
문서에서 검색을 해보면, 해당 클래스 이름을 가진 버튼들이 좌측에 시각적인 영역으로 보이게 된다.
이걸 위에서부터 번호를 붙여보면, 평가 및 리뷰 옆의 화살표 버튼은 8번째가 된다.
즉 위 코드의 반환은 class 명이 VfPpkd-Bz112c-LgbsSe 인 리스트일 뿐이고,
그 중에서 내가 원하는 버튼은 리스트의 8번째에 있다.
인덱스로 치면 [7] 이 된다.
따라서, 코드를 아래와 같이 정정한다.
수정하고 나선, 의도한대로 브라우저에 리뷰창이 뜬다.
browser.find_elements(By.CLASS_NAME,'VfPpkd-Bz112c-LgbsSe')[7].click()
4. 리뷰창 분석, 크롤링
아래 스크린샷처럼 리뷰창에서 가져올 데이터는 다음과 같다.
작성자, 작성일, 별점, 내용, 몇명에게 도움이 되었는지.
각각의 class명을 알아보면 아래 표처럼 정리가 된다.
데이터 | class 명 |
리뷰창 컴포넌트 | RHo1pe |
작성자 | X5PpBb |
작성일 | bp9Aid |
별점 | iXRFPc |
내용 | h3YV2d |
몇몀에게 도움이 되었는지 | AJTPZc |
클래스명을 확인했으면 코드를 작성한다.
코드 실행 결과는 그 아래와 같다.
#리뷰 갖고 오기 - 작성자명, 작성일, 평점, 내용, 몇명에게 도움이 되었나
datas = browser.find_elements(By.CLASS_NAME,'RHo1pe')
data_list =[]
print(len(datas))
for i in datas :
작성자 = i.find_element(By.CLASS_NAME,'X5PpBb').text
작성일 = i.find_element(By.CLASS_NAME,'bp9Aid').text
별점 = i.find_element(By.CLASS_NAME,'iXRFPc').text
내용 = i.find_element(By.CLASS_NAME,'h3YV2d').text
유용성 = i.find_element(By.CLASS_NAME, 'AJTPZc').text
print(작성자,작성일,별점,내용,유용성)
data_list.append({
'작성자 ' : 작성자,
'작성일' : 작성일,
'별점' : 별점,
'내용' : 내용,
'유용성' : 유용성
})
결과를 보면 별점이 출력되지 않고,
유용성이 숫자가 아니라 '사용자 00명이 이 리뷰가 유용하다고 평가함' 이라고 출력된다.
우선 유용성은 문자열 슬라이스를 통해 숫자만 추출한다.
처음에는 문자열 인덱스를 사용하려고 했었다.
사용자 5명 / 사용자 22명 / 사용자 145명 식으로, 숫자의 자리수가 달라짐에 따라 인덱싱을 다르게 해주어야 하므로,
split()함수를 사용해서 슬라이싱을 했다.
예를 들어, 아래와 같은 문구가 있다고 했을 때 split를 두번 사용해서 숫자만 출력할 수 있다.
# 예문
exam = '사용자 10000명이 이 리뷰가 유용하다고 평가함'
exam.split(' ')[1].split('명이')[0] #출력값 : 10000
#실제 수정한 코드
유용성 = i.find_element(By.CLASS_NAME, 'AJTPZc').text
유용성 = 유용성.split(' ')[1].split('명이')[0]
별점이 출력되지 않는 이유는 HTML에서 찾을 수 있다.
'별표 5개 만점에 1개를 받았습니다'는 일반 텍스트가 아니라,
링크를 가져올 때처럼 aria-label이라는 속성안에 들어가 있다.
따라서 하이퍼링크를 가져오던 코드처럼, get_attribute('aria-label') 함수를 사용한다.
덧붙여, '별표 5개 만점에 1개를 받았습니다' 중에서 '1개'를 추출하려고 한다.
이를 리스트해보면 아래와 같다.
내가 추출하고자 하는 인덱스는 10번과 11번으로, 이를 표현하면 [10:12]가 된다.
별 | 표 | 5 | 개 | 만 | 점 | 에 | 1 | 개 | 를 | 받 | ||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
이 부분을 수정한 코드는 다음과 같다.
별점 = i.find_element(By.CLASS_NAME,'iXRFPc').get_attribute('aria-label')[10]
이 모든 수정을 거친 완성된 코드는 아래에 있다.
그리고 실행결과는 다음과 같다.
별점이 의도한대로 표기되고, 유용성도 숫자로 추출된다.
#리뷰 갖고 오기 - 작성자명, 작성일, 평점, 내용, 몇명에게 도움이 되었나
datas = browser.find_elements(By.CLASS_NAME,'RHo1pe')
data_list =[]
print(len(datas))
for i in datas :
작성자 = i.find_element(By.CLASS_NAME,'X5PpBb').text
작성일 = i.find_element(By.CLASS_NAME,'bp9Aid').text
별점 = i.find_element(By.CLASS_NAME,'iXRFPc').get_attribute('aria-label')[10] #수정한 부분
내용 = i.find_element(By.CLASS_NAME,'h3YV2d').text
try: #수정하면서 예외처리를 겸했다.
유용성 = i.find_element(By.CLASS_NAME, 'AJTPZc').text
유용성 = 유용성.split(' ')[1].split('명이')[0]
except:
유용성 = '0'
print(작성자,작성일,별점,내용,유용성)
data_list.append({
'작성자 ' : 작성자,
'작성일' : 작성일,
'별점' : 별점,
'내용' : 내용,
'유용성' : 유용성
})
5. 스크롤
리뷰창을 그냥 크롤링 하면 한번에 20개의 리뷰만 크롤링이 된다.
21번째부터는 마우스로 스크롤을 해야만 21번째가 보이고, html에도 나타난다.
스크롤은 js를 실행하는 방식으로 구현할 수 있다.
리뷰창 같은 화면을 modal이라고 한다.
스크롤은 modal창 외의 영역을 클릭하면 리뷰창이 닫혀버리고,
반드시 modal창을 클릭하고 스크롤해야만 리뷰창이 스크롤된다.
너무 빠른 작업을 막기 위해 time함수도 같이 사용한다.
이 과정을 코딩으로 표현하면 다음과 같다.
#스크롤 구현 - js 실행
import time
#스크롤 하기 위한 크기
modal = browser.find_element(By.CLASS_NAME,'fysCi')
modal.click() #모달창 클릭
for i in range(0,5):
code = 'arguments[0].scrollTo(0,arguments[0].scrollHeight)'
browser.execute_script(code,modal) #argument = modal
time.sleep(1)
#스크롤을 끝까지 한걸 알아볼 수 있는 방법?
#모달창의 크기 만큼 스크롤 => 스크롤의 위치가 전체 높이와 같아면
# modal -> arguments[0].ClientHeight >= arguments[0].scrollHeight
포스팅에서는 4. 크롤링, 5. 스크롤 순으로 작성했다.
하지만 스크롤을 해야만 20개보다 넘는 리뷰가 뜨기 때문에 실제 실행은 스크롤 다음 크롤링이다.
6. 데이터저장
위의 datas를 데이터프레임으로 바꾼다.
그리고 데이터프레임을 csv파일로 저장했다.
#데이터프레임 변환
import pandas as pd
df = pd.DataFrame(data_list)
#csv 파일 저장
df.to_csv(f'배달의 민족.csv', encoding='utf-8-sig')
'Python' 카테고리의 다른 글
API를 통한 데이터 수집 (0) | 2024.07.12 |
---|---|
crawling 5 - SRT 예매 프로그램 (0) | 2024.07.11 |
crawling 3 - YES 24 예제 (0) | 2024.07.11 |
crawling 2 - DBPIA 예제 (0) | 2024.07.11 |
crawling 1 - Selenium (0) | 2024.07.10 |