본문 바로가기

Starry Day

R로 아마존 리뷰 크롤링

프롤로그

일단 난 R을 한 10년전에 대학원 때 베이직 코스를 들어 지금은 다 까먹었고, 사실 그때도 완벽하게 이해한 것은 아니라 지금 내 업무에 필요한 부분만 인터넷에서 찾아서 사용하고 있는 상황이다. 그런데 왜이렇게 오류는 많이 나고 패키지는 왜이렇게 많이 깔라고 하는 것인지... 그러다 별 문제 없이 아마존 사이트 크롤링에 워드 클라우드 생성, 심지어 응용해서 워드클라우드 텍스트에 색까지 완벽하게 입힐 수 있는 스크립트를 찾아 이렇게 글을 써본다.

스크립트는 아래 Musings on R 블로그 작가님과 개발자포럼인 stsaxkoverflow.com에서 가져왔다.

https://martinctc.github.io/blog/vignette-scraping-amazon-reviews-in-r/

 

Vignette: Scraping Amazon Reviews in R

Background One of the pet projects that I had been working on earlier in the year was to figure out an efficient way to gain an insight into what is going on in a consumer market, e.g.: What do people look for when they’re buying a product? What are the ty

martinctc.github.io

https://stackoverflow.com/questions/25505145/how-to-make-r-word-cloud-display-most-frequent-term-in-lighter-shade-of-color

 

How to make R word cloud display most frequent term in lighter shade of color

I created a word cloud in R with the code: wordcloud(words$term, words$freq, random.order=FALSE, colors=colorRampPalette(brewer.pal(9,"Blues"))(32), scale=c(5, .5)) And it works fine only that it

stackoverflow.com

 

아마존 리뷰 크롤링

첫번째 페이지 크롤링

일단 기본 패키지부터 불러온다.

library(tidyverse) #기본 패키지 불러오기
library(rvest)

그 다음이 중요한데, 검색하려는 상품의 ASIN을 알아야한다고 한다. 원하는 제품의 페이지 들어가서 페이지 내에서 ASIN을 검색하면 중간쯤에 찾을 수 있다. 스크립트에 크롤링하려는 제품의 웹주소가 필요하기 때문인데, 보통 "https://www.amazon.com/dp/ + ASIN" 이기 때문이다. 

일단 작가가 활용한 ASIN과는 다른, 내 업무에 필요한 제품리뷰 ASIN B07P6T82LC 를 가지고 스크립트를 공유해본다:

scrape_amazon <- function(ASIN, page_num){
  
  url_reviews <- paste0("https://www.amazon.com/product-reviews/",ASIN,"/?pageNumber=",page_num)
  
  doc <- read_html(url_reviews) #  `doc` 에 결과 입히기
  
  # 리뷰 제목
  doc %>% 
    html_nodes("[class='a-size-base a-link-normal review-title a-color-base review-title-content a-text-bold']") %>%
    html_text() -> review_title
  
  # 리뷰 글
  doc %>% 
    html_nodes("[class='a-size-base review-text review-text-content']") %>%
    html_text() -> review_text
  
  # 리뷰에 별 몇개인지
  doc %>%
    html_nodes("[data-hook='review-star-rating']") %>%
    html_text() -> review_star
  
  # Return a tibble
  tibble(review_title,
         review_text,
         review_star,
         page = page_num) %>% return()
}

그리고 이제 아래 스크립트로 결과를 테이블로 꾸며서 볼 수 있음:

scrape_amazon(ASIN = "B07P6T82LC", page_num = 5) %>%
  head()
여러 페이지 크롤링

리뷰가 첫 장을 넘어가게 되는 경우에 사용되는 스크립트인데, 1-10 페이지를 크롤링한다고 가정하고 아래 스크립트 돌리면 10페이지까지 크롤링이 가능하다.

ASIN <- "0007477155" # ASIN 명시하기
page_range <- 1:10 #  1 ~ 10 페이지까지 크롤링한다고 함

# Create a table that scrambles page numbers using `sample()`
# For randomising page reads!
match_key <- tibble(n = page_range,
                    key = sample(page_range,length(page_range)))

lapply(page_range, function(i){
  j <- match_key[match_key$n==i,]$key

  message("Getting page ",i, " of ",length(page_range), "; Actual: page ",j) # 프로그레스 바

  Sys.sleep(3) # 3초 쉬어줌. 아마존이 내 IP를 막는 것을 방지하기 위함

  if((i %% 3) == 0){ # 3번 크롤링 후 2초씩 쉼
    
    message("Taking a break...") # 쉴때 'taking a break' 메시지 보여줌
    
    Sys.sleep(2) # 추가 2초 쉼
  }
  scrape_amazon(ASIN = ASIN, page_num = j) # 크롤링 가져옴
}) -> output_list

 

워드 클라우드 생성하기

이제 수집한 데이터를 아래 스크립트로 워드클라우드를 만들어보자.

output_list %>% 
   bind_rows() %>%
   unnest_tokens(output = "word", input = "review_text", token = "words") %>%
   count(word) %>%
   filter(!(word %in% c("phone","the, "LG","screen","phones","sprint"))) %>%
   anti_join(tidytext::stop_words, by = "word") -> word_tb

pal = brewer.pal(9,"BuPu") #예쁜 파란색과 보라색으로 설정
wordcloud::wordcloud(
 words = word_tb$word, 
 freq = word_tb$n,
 scale = c(6,.3), #클라우드 크기 관련..너무 작거나 크면 6이라고 쓰여진 부분 수정
 random.color = F, 
 random.order = F,
 colors = pal)  #색은 pal활용 

 

그럼 짜잔~ 이렇게 예쁜 워드 클라우드 생성되는 것을 볼 수 있다. 보니까 love, happy, excellent, awesome과 같은 긍정적인 리뷰도 있는 반면에 issue, disappointed, bad, 이런 부정적인 리뷰도 있는 것을 볼 수 있다.

글을 마치며

워드 클라우드를 마치고, 이제 자주 언급된 단어들을 언급순으로 나열하고, 몇번 언급됐는지를 보여주는 테이블을 만들고 싶은데...반나절 찾아서 해보다가 계속 오류나서 포기해버렸다. 역시 기본이 안되어 있으니 응용이 쉽지 않다 ㅠㅜ...혹시 이 스크립트 활용해 내가 만들고 싶은 테이블 만드는 법 아는 분은 리플 달아주기를~~ 그럼 이만 안녕~~