Final project

영화 리뷰 분석

송지원

제가 분석할 영화는 더리더: 책 읽어주는 남자 입니다. 영화 리뷰를 분석하기에 앞서 분석할 리뷰를 크롤링 해줍니다. R을 활용한 크롤링은 이 곳을 참고하였습니다.

link

영화리뷰 크롤링

library(XML) #크롤링하는데 필요한 패키지 다운로드 후 불러오기
library(stringr)

all_reviews <- NULL
url_base <- "https://movie.naver.com/movie/bi/mi/pointWriteFormList.nhn?code=45298&type=after&onlyActualPointYn=N&order=newest&page="

for (i in 1:240) { #1:240이 1부터 240까지 반복한다는 뜻. 한페이지 리뷰수10개 x240페이지 = 리뷰 2400개
  newr <- NULL
  url <- paste(url_base, i, sep='')
  txt <- readLines(url, encoding="UTF-8", warn=FALSE)
  
  reviews <- txt[which(str_detect(txt, "id=\"_filtered_ment"))+4] #class=score_reple를 찾으면 네이버에서 댓글스포방지를 추가해서 태그가 하나가 더 생겼습니다 그래서 차라리 위에처럼하고 4줄뒤에부터 불러오면 댓글을 가져올 수 있습니다
  reviews <- gsub("<.+?>|\t","", reviews) #특수문자 제거
  
  newr <- cbind(reviews)
  all_reviews <- rbind(all_reviews, newr)
}

write.table(all_reviews, "C:\\Temp\\movie_review.txt") #저장하는 코드

텍스트 마이닝

가장 많이 사용된 단어 알아보기

library(KoNLP)
## Checking user defined dictionary!
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(RColorBrewer)
library(wordcloud)

useSejongDic() #텍스트 마이닝을 하는데 필요한 패키지들을 불러옵니다.
## Backup was just finished!
## 370957 words dictionary was built.
review<-readLines("movie_review.txt") #데이터 불러오기


review<-str_replace_all(review,"\\W"," ") #특수문자 제거
#gsub을 이용해 분석에 불필요한 것들을 제거해줍니다.
review<-gsub("\\d+","",review) #숫자제거
review<-gsub("\\n+","",review) #새로운 줄 제거
review<-gsub("[A-z]","",review) #영어알파벳 제거
reviewt<-gsub("진짜","",review) #분석에 중요하지 않은 단어 제거
review<-gsub("영화","",review) #분석에 중요하지 않은 단어 제거

nouns<-extractNoun(review) #크롤링한 리뷰에서 명사만 추출
wordcount<-table(unlist(nouns)) #추출한 명사 list를 문자열 백터로 변환, 단어별 빈도표 생성
re_word <- as.data.frame(wordcount, stringsAsFactors = F) #데이터 프레임으로 변환
re_word<-rename(re_word,word=Var1,freq=Freq) #변수명 수정
re_word<-filter(re_word,nchar(word)>=2) #두 글자 이상 단어 추출

top20<-re_word %>% arrange(desc(freq)) %>% head(20) #상위 20개 단어 추출
top20
##      word freq
## 1    사랑  340
## 2    가슴  167
## 3    감동  159
## 4    여운  135
## 5    생각  128
## 6    연기  122
## 7    최고   97
## 8  케이트   93
## 9    마음   83
## 10   눈물   81
## 11   그녀   80
## 12   남자   79
## 13          77
## 14   하게   76
## 15   이해   74
## 16   인생   59
## 17   잔잔   54
## 18 윈슬렛   52
## 19   감정   49
## 20 첫사랑   48

워드 클라우드 만들기

pal<-brewer.pal(8,"Dark2")
set.seed(1234)

wordcloud(words = re_word$word,
          freq = re_word$freq,
          min.freq =2,
          max.words = 200,
          random.order = F,
          rot.per = .1,
          scale = c(4, 0.3),
          colors = pal)

감성분석

감성분석에 관한 코드는 이곳을 참고했습니다. link

library(plyr)
## ------------------------------------------------------------------------------
## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)
## ------------------------------------------------------------------------------
## 
## Attaching package: 'plyr'
## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
library(stringr) #감성분석에 필요한 패키지 불러오기
txt<-readLines("movie_review.txt") #데이터를 txt로 가져오기
 
#군산대 감성사전을 사용했습니다. 

positive <- readLines("positive.txt", encoding = "UTF-8") #감성사전 변수생성
## Warning in readLines("positive.txt", encoding = "UTF-8"): 'positive.txt'에서 불
## 완전한 마지막 행이 발견되었습니다
positive=positive[-1]
negative <- readLines("negative.txt", encoding = "UTF-8")
## Warning in readLines("negative.txt", encoding = "UTF-8"): 'negative.txt'에서 불
## 완전한 마지막 행이 발견되었습니다
negative=negative[-1]

#감성분석 코드는 처음 해보는 코드라 참고자료 그대로 사용했습니다.
sentimental = function(sentences, positive, negative){
  
  scores = laply(sentences, function(sentence, positive, negative) {
    
    
    
    sentence = gsub('[[:punct:]]', '', sentence) # 문장부호 제거
    
    
    sentence = gsub('[[:cntrl:]]', '', sentence) # 특수문자 제거
    sentence = gsub('\\d+', '', sentence)        # 숫자 제거
    
    word.list = str_split(sentence, '\\s+')      # 공백 기준으로 단어 생성 -> \\s+ : 공백 정규식, +(1개 이상)
    words = unlist(word.list)                    # unlist() : list를 vector 객체로 구조변경
    
    pos.matches = match(words, positive)           # words의 단어를 positive에서 matching
    neg.matches = match(words, negative)
    
    pos.matches = !is.na(pos.matches)            # NA 제거, 위치(숫자)만 추출
    neg.matches = !is.na(neg.matches)
    
    score = sum(pos.matches) - sum(neg.matches)  # 긍정 - 부정   
    return(score)
  }, positive, negative)
  
  scores.df = data.frame(score=scores, text=sentences)
  return(scores.df)
}

감성분석 결과 도표 만들기

result=sentimental(txt, positive, negative) #감성분석 결과에 리뷰,긍정,부정 사전 불러오기
 
result$color[result$score >=1] = "blue" #긍정일 경우 파란색
result$color[result$score ==0] = "green" #중립일 경우 초록색
result$color[result$score < 0] = "red" #부정일 경우 빨간색

table(result$color)
## 
##  blue green   red 
##   466  1659   276
result$remark[result$score >=1] = "긍정"

result$remark[result$score ==0] = "중립"

result$remark[result$score < 0] = "부정"

sentiment_result= table(result$remark)



pie(sentiment_result, main="감성분석 결과",
    
    col=c("blue","red","green"), radius=0.8)

sentiment_result
## 
## 긍정 부정 중립 
##  466  276 1659