투빅스 11기&12기 8주차 NLP기초 - 12기 박진혁

by 박진혁 posted Sep 21, 2019
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

+ - Up Down Comment Print

친절한 금자씨 왓챠 평점데이터를 평점별로 분석해서 각 평점을 준 사람들은 어디에 포인트를 두고 영화를 봤는 지
특정 장면에 대해 어떻게 생각했는 지를 추출해볼 예정입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
 
import time
from time import sleep
import re
from tqdm import tqdm
from random import randint
import requests
from bs4 import BeautifulSoup as bs
import random
import json
import csv
 
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
 
 
watcha_url = 'https://watcha.com/ko-KR/contents/mdRL9gW/comments' #친절한 금자씨 코멘트 주소
headers = {'User-Agent''Mozilla/5.0 (Macintosh; InteSl Mac O X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
response = requests.get(watcha_url,headers= headers)
 
 
 
#왓챠에서 친절한 금자씨 크롤링할 예정임!
#로그인하고 하는 과정은 수동으로 했음.
#왓챠는 robots.txt해본결과 크롤링 가능!
browser = webdriver.Chrome()
browser.get(watcha_url)
 
# Get scroll height
last_height = browser.execute_script("return document.body.scrollHeight")
 
## 스크롤 down하는건 구글링해서 코드를 참조했고 출처 링크!
while True:
    # Scroll down to bottom
    browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    # Wait to load page
    time.sleep(0.5)
    # Calculate new scroll height and compare with last scroll height
    new_height = browser.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height
#출처 : https://cnpnote.tistory.com/entry/PYTHON-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C-selenium-webdriver%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9B%B9-%ED%8E%98%EC%9D%B4%EC%A7%80%EB%A5%BC-%EC%8A%A4%ED%81%AC%EB%A1%A4%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C
 
 
 
sub = browser.find_elements_by_css_selector('#root > div > div.css-d3s16q-NavContainer.ebsyszu0 > section > section > div > div > div > ul > div ')
# Comment_sub로 평점 및 평가가 모두 들어간 데이터 자료!
# 일단 이걸 다 긁어 온 다음에 여기서 평점과 평가를 같이 추출할 생각
grad_list =[]
comment_list =[]
from tqdm import tnrange
for item in sub:
    #평점이 없으면 그냥 None을 달고 아니면 평점을 넣기
    try:
        grad_list.append(item.find_element_by_css_selector('div > div.css-6j702-TitleContainer.e1oskw6f1 > div.css-1eyufz5-UserActionStatus.e1oskw6f4 > span'))
    except:
        grad_list.append(None)
    try:
        comment_list.append(item.find_element_by_css_selector('div.css-103yoki-TextBlock.e1oskw6f3 > div > span'))
    except:
        comment_list.append(None)
 
 
list_5 = []
list_4 = []
list_3 = []
list_2 = []
list_1 = []
# 각 별점별 리스트 5는 4.5~ 5점
# 4는 3.5~4점같은식이다.
from tqdm import tnrange
for i in tnrange(len(sub)):
    if grad_list[i] != None:
        if grad_list[i].text == '5.0' or grad_list[i].text =='4.5':
            list_5.append(comment_list[i].text)
        elif grad_list[i].text == '4.0' or grad_list[i].text =='3.5':
            list_4.append(comment_list[i].text)
        elif grad_list[i].text == '3.0' or grad_list[i].text =='2.5':
            list_3.append(comment_list[i].text)
        elif grad_list[i].text == '2.0' or grad_list[i].text =='1.5':
            list_2.append(comment_list[i].text)
        elif grad_list[i].text == '1.0' or grad_list[i].text =='0.5':
            list_1.append(comment_list[i].text)
 
 
import numpy as np
import pandas as pd
from konlpy.tag import *
 
twitter = Okt()  
komoran = Komoran()
kkma = Kkma()
hannanum = Hannanum()
 
 
print(len(list_1))
print(len(list_2))
print(len(list_3))
print(len(list_4))
print(len(list_5))
#1 2는 너무 작으므로 쓰지 않기로 결정
# list_3 4 5만으로 분석해봐야겠다. 그런데 지금생각해보면 그냥 1 2 3을 묶어서 했어도 괜찮았을 듯!
 
twitter = Okt()  
# 조사 부분 제거 코드는 그대로 쓰되, 구두점도 같이 제거, 실제 구두점도 넣어서해보면 결과가 왜곡됨. 
def make_corpus_rm_stopwords(text):
    corpus = []
    for s in text.split('\n'):
        corpus.append(['/'.join(p) for p in twitter.pos(s) if (p[1!= "Josa"and (p[1!= "Punctuation")]) 
    return corpus
 
 
from tqdm import tqdm
corpus_3= []
corpus_4= []
corpus_5= []
for i in range(len(list_3)):
    temp = make_corpus_rm_stopwords(list_3[i])
    for item in temp:
        corpus_3.append(item)
for i in range(len(list_4)):
    temp = make_corpus_rm_stopwords(list_4[i])
    for item in temp:
        corpus_4.append(item)
for i in range(len(list_5)):
    temp = make_corpus_rm_stopwords(list_5[i])
    for item in temp:
        corpus_5.append(item)
        
# 각 별점별로 말꾸러미 만드는 코드!
 
from gensim.models import Word2Vec, FastText
 
 
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
 
# tsne로 만들어서 plot하는 코드.. 이건 구글링해서 출처 표시!
# tsne로 만든 이유는 단어의 관계를 보기에 가장 적합한 것이라고 생각했기 때문.
def tsne_plot(model):
    "Creates and TSNE model and plots it"
    labels = []
    tokens = []
 
    for word in model.wv.vocab:
        tokens.append(model[word])
        labels.append(word)
    
    tsne_model = TSNE(perplexity=40, n_components=2, init='pca', n_iter=2500, random_state=23)
    new_values = tsne_model.fit_transform(tokens)
    plt.rc('font', family='NanumGothic')
 
    x = []
    y = []
    for value in new_values:
        x.append(value[0])
        y.append(value[1])
    plt.figure(figsize=(1616)) 
    for i in range(len(x)):
        plt.scatter(x[i],y[i])
        plt.annotate(labels[i],
                     xy=(x[i], y[i]),
                     xytext=(52),
                     textcoords='offset points',
                     ha='right',
                     va='bottom')
    plt.show()
    #https://www.kaggle.com/jeffd23/visualizing-word-vectors-with-t-sne
 
 
FT_SG_model_3 = FastText(corpus_3, size=10, window=3, min_count=4, workers=4, iter=1000, sg=1)
# SKip gram이랑 CBOW를 사용해볼 예정!, Word2Vec은 잘 안쓰이니 굳이 시도해볼 필요는 없을 듯
# 그리고 parameter의 경우 일단 window는 3으로 했고(보통 2를 쓰지만 평점이므로 조금 더 길게 써 봄! size는 계산속도를 고려해서 골랐고
# min_count는 내가 눈에 잘 보이는 정도의 양이 나올때까지 바꿔가면서 사용함!)
 
tsne_plot(FT_SG_model_3) # 3일때
 
 
FT_SG_model_4 = FastText(corpus_4, size=10, window=3, min_count=24, workers=4, iter=1000, sg=1)
tsne_plot(FT_SG_model_4) #4 일때 
#min_count는 아무래도 표본 데이터수가 압도적으로 많으므로 꽤나 많이 올려야 비슷하게 나옴
 
FT_SG_model_5 = FastText(corpus_5, size=10, window=3, min_count=24, workers=4, iter=1000, sg=1)
#5일 때
 
tsne_plot(FT_SG_model_5)
 
 
FT_SG_model_3_1 = FastText(corpus_3, size=10, window=3, min_count=4, workers=4, iter=1000, sg=0)
# 이건 3인데 Tombow인 경우!
 
 
tsne_plot(FT_SG_model_3_1)
 
 
FT_SG_model_4_1 = FastText(corpus_4, size=10, window=3, min_count=24, workers=4, iter=1000, sg=0)
#4인경우
 
tsne_plot(FT_SG_model_4_1)
 
 
FT_SG_model_5_1 = FastText(corpus_5, size=10, window=3, min_count=24, workers=4, iter=1000, sg=0)
#5인경우
 
tsne_plot(FT_SG_model_5_1)
 
 
# Insight !
 
# 두 가지 모델을 모두 돌려본결과 저는 CBOW가 더 제가 원하는 결과를 잘 도출해 준것 같아 CBOW를 선택했습니다.
# 저는 평점별로 친절한 금자씨 평을 마이닝해서 높은 점수 보통점수를 준사람들이 각각 어떤 부분에 더 집중했는 지를 보고자 했습니다.
 
# 1. 평점을 2.5~3점으로 준 사람의 경우 : '최고'라는 단어가 취향이라는 단어와 연관이 깊다는 것으로 나왔습니다. 즉 최고의 작품이라고 볼 수도 
# 있지만 본인에게는 취향을 탄다거나 호불호가 갈릴 수 있는 영화라는 점을 썼던 것이 아닐까라고 생각합니다.
# 이것을 뒷받침 해주는 것이 '나'라는 명사와 '별로'라는 명사가 같이 등장했다는 것입니다. 즉, 나에게는 별로였다라고 한 사람들이 많았다는거죠.
# 잘보면 이 외에도 '역시' '그렇게' '모르겠다' 등의 단어가 군집되어있습니다.
# 그 외에도 특유의 미쟝셴 등의 단어가 나타나기는 하지만, 다른 단어와의 연관성이 커 보이지는 않습니다.
# 3부작 이라는 단어가 등장했습니다. 그런데 여기서 특이한 점은 3부작 이라는 단어와 2라는 단어가 같이 등장한다는건데요.
# 유일하게 3점대에서만 2라는 숫자가 등장합니다!
# 거기다 올드보이라는 단어가 최고라는 단어와 같이 3부작 쪽에 있습니다. 
# 즉, 올드보이 다음 작품으로 인식한 사람이 많았다는 걸로 해석할 수 있다고 생각됩니다.
 
# 2. 평점을 3.5~4점으로 준 사람의 경우 :
#그리고 이영애 연기 연출 느낌 등이라는 단어가 비슷하게 위치한 것으로 보아
# 이 영화를 전반적으로 이영애가 준 연기와 그 느낌에 감동한 사람이 많을 것이라고 생각됩니다.
# 그리고 여기서는 두부, 하얀 이라는 단어가 군집되어있는 것을 볼 수 있는데요. 사실, 두부와 하얀색은
# 이 영화를 깊게 보지않으면 잘 느끼기 힘든 부분입니다. 즉 4점에 가까운 점수를 준 사람들은 영화의 숨은 의미를 찾기 시작했다는 거죠!
# 또한 미장셴 이라는 단어에 매력 가장 잘 느낌 등의 단어가  등장하며 멀지않은 곳에 이영애 음악 영상 등의 키워드가 추가로 군집돼있습니다.
# 즉 4점대 이상을 택한 사람들은 이 영화의 미쟝셴에 조금씩 영향을 받기 시작했다고 할 수 있다고 생각합니다.
 
# 3. 평점을 4.5~5점으로 준 사람의 경우 : 확실히 단어 표현이 풍부해졌습니다. 3.5~4점과 비교해서 같은 양의 min_count를 사용하였는데도
# 훨씬 더 풍부한 어휘가 나온 것으로봐서는, 훨씬 더 평이 길어졌다고 생각할 수 있을 것입니다.
# 그만큼 이 영화를 다양한 관점에서 바라볼 수 있는 배경이 있었다는 뜻으로도 볼 수 있겠죠.
# 그리고 여기서는 미쟝셴을 중심으로 한 단어가 훨씬 풍부해졌습니다. 연기 연출 표정 음악 분위기 배우 등 훨씬 더 다양한 표현이
# 미쟝셴과 같이 언급되었는데요. 5점대 사람들의 경우 이 영화의 모든 미쟝셴에 만족했다고 볼 수 있을 것입니다. 그런데 변태가 같이 언급되네요.
# 저는 이 영화를 보면서 변태와 미쟝셴이 연결되는 느낌을 받지는 못했습니다. 그래서 제가 5점을 주지 못한걸까요?
# 그리고 굉장히 특이한 점은 하나 본 듯 이라는 군집이 눈에 띕니다. 하나 본 듯, 어디서 많이 본 표현이죠?
# 제 생각에는 뛰어난 ~를 본 듯 뛰어난 뮤지컬을 한 편 본 듯과 같이 비유적인 표현, 걸작이라는 표현을 하기 위해 사용했다고 생각합니다.
# 그리고 한국 여성 캐릭터 중 최고 등의 어휘가 군집이 되어있습니다. 여성이 주인공이 되어 서사를 이끌어나간 포인트에 집중한
# 사람이 많다고 생각됩니다. 또 하얀이라는 단어가 붉은이라는 단어와 더욱 밀접하게 연관되어 있습니다.
# 이것은 4점과 다른 점인데 저는 붉은 립스틱과 하얀 눈 등의 관계를 영화를 보면서 느끼지 못했고 오히려 
# 하얀 두부 등에 더욱 집중했는데, 5점을 준 사람은 이런 부분에 더욱 집중한 것 같네요.
 
# 그리고 전반적으로 너나 잘하세요 라는 군집이 꽤 많이 나오는데요. 저는 이 단어가 주로 어디와 연결되는지 보고 싶은마음에
# 따로 제외하지는 않았습니다. 그런데 약간 뚝 떨어져있는 경향이 평점대에 관계없이 보이네요.
# 그렇다는 이야기는 그냥 마지막에 이 단어를 썼다는거겠죠? 그런데 CBOW 5점대 의경우 '하세요'가 떨어져있습니다.
# 이것은 전 분석에서 이 부분만의 특이점이라고 생각됩니다. 
 
# 그런데 SG를 0으로 하나 1로 하냐에 따라 약간 군집이 다르게 되어있습니다. 저는 전반적으로 두 번째 결과가 더 군집화가 잘 되어 있다고
# 판단되어 두번째 것을 썼지만, 오히려 첫 번째 것도 군집이 깔끔하게 되어 있는 부분도 꽤 있습니다.
# 두 가지를 모두 활용해서 인사이트를 도출해내는 것도 괜찮을 것 같네요!
 
 
 
 
 
cs

Articles

2 3 4 5 6 7 8 9 10 11

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5