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