구글 플레이스토어 앱 리뷰를 수집하여, 수집한 리뷰데이터 KOMORAN 라이브러리를 통해 명사만 추출하여 해당 앱들의 키워드를 worldCloud로 뿌려주는 기능을 개발하게 되었다. 

 

해당 기능을 개발하면서 겪었던 오류나 개발하면서 알게되었던 내용을 정리해보고자 한다.

 

 

1. 셀레니움 설치 전 Chrome 버전 확인

: Chrome 오른쪽 상단 ...  → 설정 → Chrome 정보에서 버전 확인 

2. Chrome Driver 설치하기

 

ChromeDriver - WebDriver for Chrome - Downloads

Current Releases If you are using Chrome version 115 or newer, please consult the Chrome for Testing availability dashboard. This page provides convenient JSON endpoints for specific ChromeDriver version downloading. For older version of Chrome, please see

chromedriver.chromium.org

ChromeDriver 홈페이지에서 위에서 확인한 자신의 Chrome버전과 맞는 Driver를 설치해줘야 한다.

 

 

3. pom.xml에 라이브러리 추가 (url : https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java)

<dependency>
	<groupId>org.seleniumhq.selenium</groupId>
	<artifactId>selenium-java</artifactId>
	<version>3.141.59</version>
</dependency>

 

4. 구글 플레이스토어 앱 리뷰 크롤링 하기

내가 수집하고자 하는 데이터는 다음과 같았다. ( 사용자 이름, 리뷰내용, 별점, 좋아요 수, 작성일자 )

 

구글플레이 스토어에서 앱에 대한 리뷰가 최대 3개밖에 보이지 않아서,  "모든 리뷰 보기" 버튼 클릭하는 코드를 추가해야했다.

 

 

F12(개발자 도구)를 누르면 해당 페이지의 HTML 코드를 볼 수 있어서 웹 페이지가 어떻게 구성되어 있는지 쉽게 파악할 수 있다.

 

4-1) 구글플레이스토어 웹 페이지 띄우기

public void getReivew() throws InterruptedException {
		
		System.setProperty(chromeDriverName, chromeDrvierPath);
		//크롬 드라이버 셋팅 (드라이버 설치한 경로 입력)
		
		ChromeOptions options = new ChromeOptions();
		options.addArguments("--no-sandbox")
			.addArguments("--disable-dev-shm-usage")
			.addArguments("--disable-blink-features=AutomationControlled");
		
		
		driver = new ChromeDriver(options);
		driver.get(url);    
 }

 

4-2) 리뷰 모두 보기 버튼을 클릭 했을 때, 동적 페이지 형식으로 되어있어서 모든 리뷰를 가져오기 위해서는 스크롤을 통해 맨 아래로 내리는 작업을 해줘야했다.

 

 scrollTo 함수를 사용했을 때, 리뷰 모달창이 아닌 뒤에 있는 페이지가 아래로 내려가 포커싱을 모달창에 잡아주는 과정에서 많은 시간을 소요했다.😂

 

WebElement prev_element = null ;
			
while(true) {
				
		WebElement element = driver.findElement(By.xpath("//*[@id=\"yDmH0d\"]/div[4]/div[2]/div/div/div/div/div[2]/div/div[2]/*[last()]"));
					
		if(element.equals(prev_element)) break;
					
		JavascriptExecutor.executeScript("arguments[0].scrollIntoView(true);", element);
		Thread.sleep(4000);
					
		prev_element = element;
}

i) 로딩된 리뷰 모달창에 사용자의 마지막 리뷰에 해당하는 xpath를 웹페이지에서 가져온 뒤,  해당 element 값이 prev_element 값과 동일하다면 웹 페이지에 모든 리뷰를 로딩했음을 의미하므로 종료

ii) JacascriptExecutor 를 이용해 해당 element 위치까지 스크롤를 내려주는 과정을 반복

 

[위 소스코드 결과]

 

 

4-3) 앱 리뷰 데이터 파싱해서, 내가 원하는 데이터로 가공해 적재하기

public void dataParsing(WebDriver driver, String appName) {
		List<WebElement> list = driver.findElements(By.className("RHo1pe"));

		DataMap map;
		
		try {
        
			for(int i=0;i<list.size();i++) {
				String[] str = list.get(i).getText().split("\\n");
				
				map = new DataMap();
				map.put("appName", appName);
				map.put("userName", str[0]);
				map.put("contents", str[3]);
		
				String score = list.get(i).findElement(By.xpath("//*[@id=\"yDmH0d\"]/div[4]/div[2]/div/div/div/div/div[2]/div/div[2]/div[38]/header/div[2]/div")).getAttribute("aria-label")
						.replaceAll("[^0-9]", "");
				map.put("score", Integer.parseInt(score.substring(score.length()-1)));
			
				String thumbsUp = str[4].replaceAll("[^0-9]", "");
				thumbsUp = thumbsUp.length()==0 ? "0" : thumbsUp;
				map.put("thumbsUp", Integer.parseInt(thumbsUp));

				map.put("cretDt", compareFormat.parse(str[2]));
				
				googlePlayStoreReviewMapper.insertReviewData(map);
			}
			
		} catch (ParseException e) {
			// catch
		}
	}

 

[앱 리뷰 데이터 파싱 결과]

 

 

## 2023-06-15 추가 

1) 매번 모든 리뷰를 파싱하면 비효율 적이므로, 최신 순으로 정렬 후 앱에 해당하는 마지막 리뷰일자를 찾아 그 이후 날짜에 해당하는 리뷰만 파싱해 올 수 있도록 코드를 수정했다.😊

'정리 > Java' 카테고리의 다른 글

ListIterator  (0) 2021.10.20

Iterator<E> 인터페이스

  • 컬렉션에 저장된 요소를 읽어오는 방법을 iterator인터페이스로 표준화
    LinkedList<Integer> list = new LinkedList<Integer>(); 
    
    list.add(4); 
    list.add(3); 
    list.add(2); 
    list.add(1); 
    
    Iterator<Integer> iter = list.iterator(); 
    
    while(iter.hasNext()){ //hasNext : 다음 요소를 가지고 있으면 true / 아니면 false 반환 
    	System.out.print(iter.next()+" "); //next : 다음 요소 반환 
    } 
    
    // 4 3 2 1​

 

ListIterator<E> 인터페이스

  • Iterator 인터페이스를 상속받아 여러 기능을 추가한 인터페이스
  • Iterator 인터페이스는 컬렉션 요소에 접근할 때 한 방향으로만 이동할 수 있지만 ListIterator 인터페이스는 양방향으로 이동할 수 있다.
LinkedList<Integer> list = new LinkedList<Integer>(); 

list.add(4); 
list.add(2); 
list.add(3); 
list.add(1); 

ListIterator<Integer> iter = list.listIterator(); 

while (iter.hasNext()) { //hasNext : 순방향으로 순회할 때 다음 요소가 있으면 true 아니면 false 
	System.out.print(iter.next() + " "); //next : 다음 요소를 반환하고 커서 위치 순방향으로 이동 
} 

while (iter.hasPrevious()) { //hasPrevious : 역방향으로 순회할 때 다음 요소가 있으면 true 아니면 false 
	System.out.print(iter.previous() + " "); //previous : 이전 요소를 반환하고 커서 위치 역방향으로 이동 
} 

// 4 2 3 1 
// 1 3 2 4

+ Recent posts