본문 바로가기
파이썬(Python)

[파이썬/Python] '아바타2 : 물의 길' 댓글 수집 및 리뷰 분석해보기

by Serendipity_ 2023. 1. 3.
반응형

오랜 만에 영화관에서 봐야만 하는 영화 ! 아바타 2 : 물의 길을 보고 왔습니다.

제임슨 카메론 감독 진짜 미쳤습니다.. 

영상미 너무 좋았고 3시간 러닝타임이 긴 줄도 몰랐어요

 

안 보신 분들 꼭 추천드립니다 !! 저는 3D로 봤는데 기회가 되면  IMAX 나 4D로 볼 것 같아요

(자리가 없어서 못봤습니다) 

아바타-물의 길 줄거리
아바타-물의 길 줄거리

댓글을 한번 보겠습니다.

댓글은 왜 이렇게 악평이 많은거죠..? 

존잼인데 말입니다..

 

그래서 댓글들을 쭉 수집해서 긍정평이 많은 지, 부정평이 많은 지 한번 분석해보도록 하겠습니다. 

 

우선 댓글 수집을 해야될 것 같습니다. 

1. 아바타2 : 물의 길 댓글 수집하기 (크롤링)

이 블로그에서 많이 다룬  Selenium 댓글 수집 주제입니다. 

그래서 이번에는 코드만 공유하겠습니다. 

 

from csv import writer
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import pandas as pd
from selenium.common.exceptions import NoSuchElementException
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
from tqdm import tqdm

options = webdriver.ChromeOptions()
options.headless = True
wd = webdriver.Chrome(service=Service(
    ChromeDriverManager().install()), options=options)

def get_movie_reviews(url, page_num=3):
    wd = webdriver.Chrome(service=Service(
        ChromeDriverManager().install()), options=options)
    wd.get(url)

    writer_list = []
    review_list = []
    date_list = []

    for page_no in tqdm(range(1, page_num + 1)):
        try:
            page_ul = wd.find_element(By.ID, 'paging_point')
            page_a = page_ul.find_element(By.LINK_TEXT, str(page_no))
            page_a.click()
            time.sleep(1)
            # print(f"======={page_no}페이지 수집 중======")

            writers = wd.find_elements(By.CLASS_NAME, 'writer-name')
            writer_list += [writer.text for writer in writers]

            reviews = wd.find_elements(By.CLASS_NAME, 'box-comment')
            review_list += [review.text for review in reviews]

            dates = wd.find_elements(By.CLASS_NAME, 'day')
            date_list += [date.text for date in dates]

            if page_no % 10 == 0:
                next_button = page_ul.find_element(
                    By.CLASS_NAME, 'btn-paging.next')
                next_button.click()
                time.sleep(0.2)

        except NoSuchElementException:
            break

    movie_review_df = pd.DataFrame({"Writer": writer_list,
                                    "Review": review_list,
                                    "Date": date_list})

    return movie_review_df

url = "http://www.cgv.co.kr/movies/detail-view/?midx=86072" # 아바타 URL 
movie_review_df = get_movie_reviews(url, 100) #댓글 수집 페이지 수 
# print(movie_review_df)
movie_review_df.to_csv('아바타댓글수집_22.1.2.csv' , encoding = 'utf-8-sig', index = False)
    
wd.quit()

이런 형태로  Selenium을 사용해서 댓글을 수집했습니다. 

 

2. 아바타2 댓글 수집 결과

아바타2_댓글수집결과
아바타2_댓글수집결과

 

데이터 프레임에서 Writer, Review, Date를 수집했습니다.

6천개 데이터를 수집해도, 4일 정도밖에 수집이 안됩니다. 텍스트 데이터양이 어마어마하네요

 

3. 텍스트 데이터 추출하기

위 데이터 프레임에서 Review 열만 가져오도록 하겠습니다. 

review_li = review['Review'].tolist()
review_li[:5]

 

리뷰열을 List화 시키고 그 중에서 앞에서 5개만 먼저 뽑아봤습니다.

리뷰 상위 5개
리뷰 상위 5개

4. Github 페이지에서 감정분석 데이터 불러오기

 

구글에 Sentiword_dict.txt라고 검색하면 가장 먼저 나오는 Github 페이지가 있습니다.

구글에 Sentiword_dict.txt라고 검색
구글에 Sentiword_dict.txt라고 검색

클릭해서 들어가보면 각종 이모티콘들 옆에 점수가 매겨져 있습니다. 

즐거운 표정에는 1점, 우울한 표정에는 -1점 같네요 

Github에 작성자 분이 저렇게 정리해주신 겁니다. 우린 이걸 사용해서 감정분석을 진행할 예정입니다. 

이모티콘_감정_점수
이모티콘 감정 점수

Python Pandas를 사용하면 파일을 다운받지 않아도 쉽게 불러올 수 있습니다.

URL은 아래 코드를 복사해서 사용해주세요 ~ 

sentdic = pd.read_csv('https://raw.githubusercontent.com/park1200656/KnuSentiLex/master/SentiWord_Dict.txt', delimiter= '\t', header = None)
sentdic.columns = ['word', 'score']
sentdic

sentdic이라는 데이터 프레임에 잘 불러왔습니다. 

 

5. 텍스트 분석 진행

# 문장 벡터화를 위함 함수 불러오기
from sklearn.feature_extraction.text import CountVectorizer
vector = CountVectorizer()

# 문장을 벡터화(띄어쓰기 기준으로 단어 분할)
bow = vector.fit_transform(review_li)

# 단어를 열이름으로 지정하기 위해 저장
term = vector.get_feature_names()

# Document Term Matrix 타입으로 데이터프레임 생성
dtm = pd.DataFrame.sparse.from_spmatrix(data = bow, columns = term)

# 형태 확인(6000개의 문장, 14325개의 단어)
dtm.shape

위 코드를 이용하면 문장을 단어별로 끊어서 단어에 대한 점수를 매길 수 있습니다. 

문맥으로 보는 게 더 정확하겠지만 우선 단어로만 보는 방법을 배워보겠습니다.

아쉬운 점은 기쁠 때나 슬플 때나 다 통용되는 단어 .. 예를 들어 ㅁㅊ (..?) 이런 단어는 무조건 Negative하게 분석했습니다. 

기존 감정분석 데이터 프레임에 따라 반응하기 때문에 그렇습니다. 

문장벡터화
문장벡터화

# 한 줄씩 0~14325번째 열까지 1이상인 열을 찾으면 해당 열이름을 가져와 감성사전에 있는지 확인 후
# 감성사전에 있으면 해당되는 점수를 가져와서 갯수와 곱한 뒤 d에 리스트로 저장, 아니면 0을 저장
# 총 6000개의 행(문장)을 모두 마치면 각 행별 리스트의 합이 ds에 하나씩 추가되서 저장됨
ds = []
for i in range(dtm.shape[0]):    
    d = []
    for j in range(dtm.shape[1]):
        if dtm.iloc[i,j]>=1:
            if sentdic.loc[sentdic.word == dtm.columns[j],'score'].empty != True:
                d.append(sentdic.loc[sentdic.word == dtm.columns[j],'score'].values[0]*dtm.iloc[i,j])
            else:
                d.append(0)
        else:
            d.append(0)
    s = sum(d)
    ds.append(s)

설명은 각주에 달았습니다.

dtm 문장을 하나씩 돌면서 열에서 1이상인 열을 찾으면 감성사전에 있는 지 확인해봅니다. 

있으면 열마다 점수를 매깁니다. 

 

지금 데이터가 6천행이다 보니 시간이 꽤 걸립니다. 셀레니움으로 데이터 수집할 때와 마찬가지로 다른 업무를 하시면서 감정분석을 하시길 추천드립니다. 그래서 저는 솔로지옥2 보고 있었습니다. 솔로지옥2 칼 갈았습니다 여러분.. 존잼이네요.

아 근데 괜히 6천행이나 했나봅니다. 너무 오래걸리네요..

 

6. 텍스트분석 평가점수 확인

0보다 크면 Positive,  0 이면 Neutral, 0보다 작으면 Negative로 Data를 수정하였습니다.

# 리뷰 리스트와 리뷰별 점수합계 결과를 데이터프레임으로 만들기
res = pd.DataFrame(list(zip(review_li, ds)), columns = ['doc','score'])

# 리뷰점수가 0보다 크면 긍정, 0이면 중립, 그외면 부정으로 판정하는 리스트 만들기
pn = []
for row in res['score']:
    if row > 0:
        pn.append('Positive')
    elif row == 0:
        pn.append('Neutral')
    else:
        pn.append('Negative')
        
# 리뷰점수 판정결과 데이터프레임에 추가
res['pn'] = pn

# 리뷰결과 데이터프레임 6개만 확인
res.head(6)

텍스트_평가점수_확인
텍스트 평가점수 확인

- 3점 내용을 보니 "호불호가 많아서 전혀 기대를 안했는데 그래픽이 정말 미친 cg 네요 영상미 하나로도 충분했던것 같습니다 초중반엔 좀 지루했지만 엄청난 cg 보는 맛에 시간 잘갔습니다 아이맥스 자리가 좋은곳이 없어서 2d로 본게 좀 아쉽긴 하네요" 라는 내용이네요.

미친 CG, 영상미 좋고 ( + ) 지루했지만 ( - ) 아쉽네요 ( - ) 여서 한 -1 점 정도나 중립정도로 가야할 것 같은데  -3점이라니.. 채점실력이 좀 아쉬운 수준입니다. 

7. 데이터 시각화(결과 파이차트) 및 결과해석

# 판정결과를 갯수기준으로 그룹화
res_g = res.groupby([pn]).count()

# 그룹화 결과 확인
res_g

# 파이차트 그리기위해 비율 계산
pct = res_g['pn']/res_g['pn'].sum()
pct

# 파이차트 그리기
import matplotlib.pyplot as plt

plt.figure(figsize=(5, 5))
plt.pie(pct, labels = res_g.index, autopct='%.1f%%', startangle = 0, counterclock = False)
plt.show()

리뷰_긍/부정_파이차트
리뷰 긍/부정 파이차트

df = pd.concat([review, res], axis = 1)
df.drop('doc', axis = 1, inplace = True)

df.sample(5)

결과적으로 모두 긍정적인 반응이지만, 평가는 0점인 것도 많습니다. 

 

결과적으로 분석 못하는 중립이 가장 많습니다.

또한, 데이터를 면밀히 보게되면 긍정인데 부정으로 해석하고, 부정인데 긍정으로 해석하는 경우도 종종 있습니다.

언어가 문맥이 아닌 단어로만 분석하는 한계라고 보이네요

 

아무튼 아바타2:물의 길은 정말 재밌게 봤던 영화입니다. 

리뷰 분석도 재미로 봐주시길 바랍니다.

반응형

댓글