<file_sep>import pandas as pd
# from tqdm import tqdm
#
# _filename = './comm_n_and_v_utf8_1_ordered_q.csv'
# encoding = 'utf-8'
# columns = ['mid', 'mname', 'score', 'genre', 'comments']
#
# read = pd.read_csv(_filename, encoding=encoding, header=None, names=columns, low_memory=False)
# tmp_mid = 0
#
# list0 = ['a', 'a', 'a', 'b']
# list1 = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['d', 'e', 'f']]
#
# count = 0
# mid_list = []
# for i in tqdm(range(0, len(read.mid))):
#     try:
#         if not read.mid[i] == read.mid[i+1]:
#             mid_list.append(count)
#     except:
#         pass
#     count += 1
# print(mid_list)
# for i in range(1, int(mid_list[0]) + 1):
#     read.comments[0].extend(read.comments[i])
#
# for i in tqdm(range(0, len(mid_list))):
#     for j in range(int(mid_list[i]) + 1, int(mid_list[i+1]) + 1):
#         if j == int(mid_list[i] + 1):
#             pass
#         else:
#             read.comments[int(mid_list[i]) + 1] = ', '.join([str(read.comments[int(mid_list[i]) + 1]), str(
#                 read.comments[j])])
#             # read.comments[int(mid_list[i]) + 1] = str(read.comments[int(mid_list[i]) + 1]) + ', ' + str(read.comments[j])
#             read.comments[j] = ''
#     print(read.comments[int(mid_list[i]) + 1])
#
# print(read.comment)


import pandas as pd
from tqdm import tqdm

# _filename = './comm_n_and_v_utf8_1_ordered_q.csv'
# encoding = 'utf-8'
# columns = ['mid', 'mname', 'score', 'genre', 'comments']
#
# read = pd.read_csv(_filename, encoding=encoding, header=None, names=columns, low_memory=False)
# tmp_mid = 0
#
# list0 = ['a', 'a', 'a', 'b']
# list1 = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'c'], ['d', 'e', 'f']]
#
# count = 0


# for i in tqdm(range(0, len(read.mid))):
#     try:
#         if not read.mid[i] == read.mid[i+1]:
#             mid_list.append(count)
#     except:
#         pass
#     count += 1
# print(mid_list)
# for i in range(1, int(mid_list[0]) + 1):
#     read.comments[0].extend(read.comments[i])
#
# for i in tqdm(range(0, len(mid_list))):
#     for j in range(int(mid_list[i]) + 1, int(mid_list[i+1]) + 1):
#         if j == int(mid_list[i] + 1):
#             pass
#         else:
#             read.comments[int(mid_list[i]) + 1] = ', '.join([str(read.comments[int(mid_list[i]) + 1]), str(
#                 read.comments[j])])
#             # read.comments[int(mid_list[i]) + 1] = str(read.comments[int(mid_list[i]) + 1]) + ', ' + str(read.comments[j])
#             read.comments[j] = ''
#     print(read.comments[int(mid_list[i]) + 1])
#
# print(read.comment)

import pickle

mid_mname_vec = {}

for _number in tqdm(range(1, 9)):
    _filename = './comm_n_and_v_utf8_' + str(_number) + '_ordered_q.csv'
    encoding = 'utf-8'
    columns = ['mid', 'mname', 'score', 'genre', 'comments']

    read = pd.read_csv(_filename, encoding=encoding, header=None, names=columns, low_memory=False)

    for i in tqdm(range(len(read.mid) - 1)):
        try:
            if not read.mid[i] == read.mid[i+1]:
                mid_mname_vec[int(read.mid[i])] = read.mname[i]
        except:
            pass

with open('../dict_mid_mname.bin', 'wb') as f:
    pickle.dump(mid_mname_vec, f)
<file_sep>from nugu.movie_comment_scrapper.crawling.naver_movie import get_movie_comm as get_comm
import os
import time
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm


with ThreadPoolExecutor(max_workers=100) as executor: # Thread
    # executor.submit(get_comm, 172816)
    for i in range(1, 200000): # 네이버 고유 영화 ID 1 ~ 200000 까지 크롤링
        executor.submit(get_comm, i)
<file_sep># NUGU_movie_recommendation  
 movie recommendation proxy server in NUGU Play
  
## 프로젝트 소개  
- SK Telecom 산학협력 인공지능 석학사 통합 교과목 진행 프로젝트
- NUGU Play Kit Platform을 이용해서 진행되었으며, 유저 맞춤형 영화 추천 서비스

## 팀 구성
- 서버 구현: [김인호](https://github.com/kih1024)
- 내부 영화 추천 알고리즘: [신태욱](https://github.com/momentum1993), [강승연](https://github.com/tmddusgood)
   
## 개발 동기  
- 혼영, 혼술 등의 여가활동을 집에서 즐기는 "홈스테이족" 증가로 인한 집에서 모든 걸 해결하는 홈코노미 관련 업종들의 뚜렷한 성장세  
- 홈코노미 서비스를 제공하는데 굉장히 적합한 플랫폼인 NUGU를 통해, 개인별 적절한 여가활동 특히 영화라는 도메인을 기반으로한 맞춤형 서비스 기획
   
## 전체 구성도  
![](./flow_chart.jpg)
  
#### 주요 기능
- 유사 영화 추천
  ex) {아이언맨} 같은 영화 추천해줘
- 유저 로그 기반 추천 (Btv 연동)
  ex) 영화 추천 해줘
- 장르 기반 추천
  ex) {스릴러} 영화 추천해줘
    
## 데이터 추출 과정
![](./data_scraping.jpg)
- 네이버 영화 페이지 → 영화 리뷰, 줄거리
- 토큰화(명사, 형용사 추출)  
- Word2vec (용언 벡터 → 영화 벡터)  
  
## 유저 로그 기반 추천 서비스
![](./user_log_based.jpg)
- 유저 로그 정보 기반 - 현재는 proxy 서버의 유저 정보 db로 부터 추출 (현재 특정 Persona에 대한 기록을 임의로 집어넣어 추천 진행)  
- 유저만의 고유 벡터 → 기록을 통한 유저만의 벡터와 그에 대한 유사한 영화 추출 (유저에 따른 추천)
  
## 장르 기반 추천 서비스
![](genre_based.jpg)
- 영화 장르 벡터 & 유저 로그 기반 → 유사 장르의 영화 추천 서비스  
- 공포(horror)라는 장르 요청의 경우: 처키, 스크림, 컨저링, 애나벨  
  
## 비슷한 영화 추천 서비스
![](similar_movie.jpg)
- 영화 별 고유 벡터 기반 - Input 영화와 비슷한 영화 추천 서비스    
- '아이언맨 같은 영화 추천해줘'의 경우: 스파이더맨, 앤트맨, 배트맨, 스타워즈, 터미네이터  
  
## 향후 발전 방향
- 현재의 영화를 이용한 서비스에서 예능, 드라마 등의 도메인 확장을 통해서 사용자들에게 더 폭넓은 추천 서비스 제공 가능  
- 스크레이핑한 데이터를 통해서 추천 서비스를 제공하고 있지만, BTV나 WAVVE의 데이터를 이용해서 연계 서비스 제공 가능  
- 시청 기록만을 통해 개인 추천 서비스를 제공하고 있지만, 컨텐츠별 시청 시간 및 사용자 패턴 분석을 통해 더욱 만족스러운 컨텐츠 추천 서비스 제공 가능
- 현재 추천에 사용되는 feature들을 더욱 세분화하거나 추가하여 구체적인 추천 서비스 제공 가능
<file_sep># 편집 거리 알고리즘

import pickle


# kor_begin = 44032
# kor_end = 55203
# chosung_base = 588
# jungsung_base = 28
# jaum_begin = 12593
# jaum_end = 12622
# moum_begin = 12623
# moum_end = 12643
#
# chosung_list = [ 'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ',
#         'ㅅ', 'ㅆ', 'ㅇ' , 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'] # 초성
#
# jungsung_list = ['ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ',
#         'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', 'ㅙ', 'ㅚ',
#         'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ', 'ㅠ',
#         'ㅡ', 'ㅢ', 'ㅣ'] # 중성
#
# jongsung_list = [
#     ' ', 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ',
#         'ㄹ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ',
#         'ㅁ', 'ㅂ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ',
#         'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'] # 종성
#
# jaum_list = ['ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄸ', 'ㄹ',
#               'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ', 'ㅂ',
#               'ㅃ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'] # 자음
#
# moum_list = ['ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ',
#               'ㅙ', 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ', 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ'] # 모음


def load_from_pickle(_string_name):
    '''
    load_from_pickle : pickle파일에서 영화 id에 대한 영화 벡터를 지니는 dict타입 객체로 반환해주는 모듈

    :param _string_name: pickle 파일 이름
    :return: 영화 id에 대한 영화 벡터를 지니는 dict타입 객체
    '''
    with open(_string_name + '.bin', 'rb') as f:
        _dict = pickle.load(f)
        return _dict


def levenshtein(s1, s2, cost=None, debug=False):
    '''
    levenshtein:

    :param s1: 비교할 단어 1
    :param s2: 비교할 단어 2
    :param cost:
    :param debug:
    :return:
    '''
    if len(s1) < len(s2): # 비교할 첫번째 단어가 두번째 단어보다 길어야 한다.
        return levenshtein(s2, s1, debug=debug) # 첫번째 단어, 두번째 단어 위치를 swap해서 알고리즘 진행

    if len(s2) == 0: # 비교할 두번째 단어가 빈칸일 때
        return len(s1) # 첫번째 단어의 길이만큼 반환

    if cost is None:
        cost = {}

    # changed
    def substitution_cost(c1, c2):
        if c1 == c2: # 만약 c1과 c2 길이가 같다면 cost = 0
            return 0
        return cost.get((c1, c2), 1) # cost dict에 (c1, c2)에 대한 value 반환하거나 없다면 1 반환

    previous_row = range(len(s2) + 1)
    for i, c1 in enumerate(s1): # 첫번째 단어에 대해 enumerate
        current_row = [i + 1] # 현재 확인할 row
        for j, c2 in enumerate(s2): # 두번째 단어에 대해 enumerate
            insertions = previous_row[j + 1] + 1 # 바로 위쪽의 cost + 1
            deletions = current_row[j] + 1 # 왼쪽의 cost + 1
            # Changed
            substitutions = previous_row[j] + substitution_cost(c1, c2) # 좌상향(↖) 대각선에 있는 cost (비교하는 알파벳 or 한글 음절이 다를 경우 +1)
            current_row.append(min(insertions, deletions, substitutions)) # 현재 열에 위의 3가지 값 중 최소값을 넣는다.

        # if debug:
        #     print(current_row[1:])

        previous_row = current_row

    return previous_row[-1]


# def compose(chosung, jungsung, jongsung):
#     char = chr(
#         kor_begin +
#         chosung_base * chosung_list.index(chosung) +
#         jungsung_base * jungsung_list.index(jungsung) +
#         jongsung_list.index(jongsung)
#     )
#     return char
#
# def decompose(c):
#     if not character_is_korean(c):
#         return None
#     i = ord(c)
#     if (jaum_begin <= i <= jaum_end):
#         return (c, ' ', ' ')
#     if (moum_begin <= i <= moum_end):
#         return (' ', c, ' ')
#
#     # decomposition rule
#     i -= kor_begin
#     cho  = i // chosung_base
#     jung = ( i - cho * chosung_base ) // jungsung_base
#     jong = ( i - cho * chosung_base - jung * jungsung_base )
#     return (chosung_list[cho], jungsung_list[jung], jongsung_list[jong])
#
# def character_is_korean(c):
#     i = ord(c)
#     return ((kor_begin <= i <= kor_end) or
#             (jaum_begin <= i <= jaum_end) or
#             (moum_begin <= i <= moum_end))
#
# def jamo_levenshtein(s1, s2, debug=False):
#     if len(s1) < len(s2):
#         return jamo_levenshtein(s2, s1, debug)
#
#     if len(s2) == 0:
#         return len(s1)
#
#     def substitution_cost(c1, c2):
#         if c1 == c2:
#             return 0
#         return levenshtein(decompose(c1), decompose(c2))/3
#
#     previous_row = range(len(s2) + 1)
#     for i, c1 in enumerate(s1):
#         current_row = [i + 1]
#         for j, c2 in enumerate(s2):
#             insertions = previous_row[j + 1] + 1
#             deletions = current_row[j] + 1
#             # Changed
#             substitutions = previous_row[j] + substitution_cost(c1, c2)
#             current_row.append(min(insertions, deletions, substitutions))
#         #
#         # if debug:
#         #     pass
#         #     # print(['%.3f'%v for v in current_row[1:]])
#
#         previous_row = current_row
#
#     return previous_row[-1]


def main(_string):
    '''
    main: 주어진 String에 대해서 존재하는 단어 중 편집거리가 가장 짧은 단어 반환
    :param _string: 편집거리를 구할 String
    :return: 영화 제목 중에 가장 편집거리가 짧은 단어 반환
    '''
    address = 'nugu/movie_story_scrapper/'
    dict_name_2 = 'dict_mid_mname'
    mid_mname = load_from_pickle(address + dict_name_2) # {영화 id: 영화제목} dict

    result = []
    weight = []
    weight_dic = {}

    for k, v in mid_mname.items():
        w = 0.01
        s1 = _string # NUGU로 부터 받은 entity
        s2 = str(v) # 현재 루프에서의 영화제목
        e_distance = levenshtein(s1, s2, debug=True) # 편집거리 알고리즘
        if e_distance < 20: # 편집거리가 20 이하인 것들에 대해서
            weight_dic[k] = e_distance # {영화 id: 편집거리} dict

    #print(weight_dic)
    result = min(zip(weight_dic.values(), weight_dic.keys()))
    print(mid_mname[result[1]])
    return mid_mname[result[1]] # 자신을 제외한 편집거리가 가장 짧은 영화 제목 반환

<file_sep>from gensim.models.word2vec import Word2Vec

model = Word2Vec.load('story_20191205_1654')

word_vectors = model.wv

print(model.wv['스타워즈'])
print(model.wv.most_similar('욕정'))
print(model.wv.most_similar('재미'))
print(model.wv.most_similar('재밌'))
print(model.most_similar(positive=['김혜수', '레이첼'], negative=['여자', '여배우'],  topn=10))
vocabs = word_vectors.vocab.keys()
word_vectors_list = [word_vectors[v] for v in vocabs]<file_sep>import pandas as pd
from tqdm import tqdm
import pickle
import re

# mid_genre_vec = {}
#
# for _number in tqdm(range(1, 9)):
#     _filename = './comm_n_and_v_utf8_' + str(_number) + '_ordered_q.csv'
#     encoding = 'utf-8'
#     columns = ['mid', 'mname', 'score', 'genre', 'comments']
#
#     read = pd.read_csv(_filename, encoding=encoding, header=None, names=columns, low_memory=False)
#
#     for i in tqdm(range(len(read.mid) - 1)):
#         try:
#             if not read.mid[i] == read.mid[i+1]:
#                 mid_genre_vec[int(read.mid[i])] = read.genre[i]
#         except:
#             pass
#
#
# with open('../dict_mid_genre.bin', 'wb') as f:
#     pickle.dump(mid_genre_vec, f)
#
# print(mid_genre_vec)

# mid_genre_dict = {}
# with open('../dict_mid_genre.bin', 'rb') as f:
#     raw_data = pickle.load(f)
#
# for k, v in tqdm(raw_data.items()):
#     mid_genre_dict[k] = re.findall(r"[\w']+", str(v))
#
# with open('../dict_mid_genre_real_eincluded.bin', 'wb') as f:
#     pickle.dump(mid_genre_dict, f)

temp_list = ["world", 'hello']
if 'world' in temp_list:
    print('hi')
else:
    print('sdfsdf')
# print(temp_list.index("world!"))

address = '../movie_story_scrapper/'
model_name = 'story_20191205_1654'  # 모델 이름
dict_name = 'dict_20191206_1937'  # 수정할것
dict_name_2 = 'dict_mid_mname'  # 수정할 것

with open(address + dict_name + '.bin', 'rb') as f:
    _dict = pickle.load(f)

print(_dict['10001'])
<file_sep>from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
import json
from pprint import pprint
from nugu.get_recommendations import main as reco
from nugu.edit_distance import main as e_distance
@csrf_exempt
def message(request):
    d = json.load(request)
    return_list = ''
    pprint(d)
    action = d['action']
    parameters = action['parameters']
    actions = action['actionName']
    # print(list(parameters.keys()))
    # condition = list(parameters.keys())
    # print(condition[0])

    if actions == "answer.like":

        movie_name = parameters['movie_name']
        v = movie_name['value']
        new_v = e_distance(v)
        return_name = reco('3', new_v)

        count = 0
        for i in return_name[:5]:
            count += 1
            print(return_name[4])
            if not count == 5:
                return_list = return_list + i + ','
            else:
                return_list = return_list + i

        print(return_list)
        # print(request.action)
        return JsonResponse({
            "version": "2.0",
            "resultCode": "OK",
            "output": {
                "movie_name": v,
                "result_movie": return_list
            }
        })
    elif actions == "answer.genre":
        movie_name = parameters['movie_genre']
        v = movie_name['value']
        print(v)
        # new_v = e_distance(v)
        return_name = reco('2', v)
        print(return_name)

        count = 0
        for i in return_name[:5]:
            count += 1
            print(return_name[4])
            if not count == 5:
                return_list = return_list + i + ','
            else:
                return_list = return_list + i

        print(return_list)
        # print(request.action)
        return JsonResponse({
            "version": "2.0",
            "resultCode": "OK",
            "output": {
                "movie_genre": v,
                "result_genre": return_list
            }
        })
    elif actions == "answer.idle":
        print("00001")
        return_name = reco('1', '1')
        print("00002")
        print(return_name)
        count = 0
        for i in return_name[:5]:
            count += 1
            print(return_name[4])
            if not count == 5:
                return_list = return_list + i + ','
            else:
                return_list = return_list + i

        print(return_list)
        # print(request.action)
        return JsonResponse({
            "version": "2.0",
            "resultCode": "OK",
            "output": {
                "return_idle": return_list
            }
        })



# Create your views here.
<file_sep>import MeCab
import pandas as pd
from tqdm import tqdm
import pickle
from gensim.models.word2vec import Word2Vec
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
import matplotlib

mc = MeCab.Tagger() # Mecab Tagger
encoding = "utf-8"
columns = ['mid', 'mname', 'score', 'genre', 'comments'] # 영화 id, 영화제목, 평점, 장르, 한줄평
md_path = './model_integrated_full(nouns+vs)'
list_pickle_path = './integrated_nouns_vs_list'
raw_path = './comm_raw_utf8_' #
fixed_path = './comm_fixed_utf8_'
n_and_v_path = './comm_n_and_v_utf8_'


def parse_Nouns_Vs(_text):
    '''
    parse_Nouns_Vs : 한줄평을 받아와서 명사와 용언을 뽑아내는 함수
    :param _text: 한줄평(str)
    :return: 명사(Noun)과 용언(Verb)을 가지는 리스트
    '''
    _answer = []
    _list = _text.split()
    for i in range(1, len(_list), 2):
        if _list[i].startswith('NN') or _list[i].startswith('V'): # 명사와 용언으로 된 것을 뽑아낸다
            _answer.append(_list[i-1])
    return _answer # 명사와 용언을 포함하는 리스트 반환

def readcsv(_filename):
    '''
    readcsv : 해당 위치의 csv파일을 DataFrame타입 객체로 반환
    :param _filename: csv파일 위치
    :return: DataFrame객체
    '''
    _read = pd.read_csv(_filename, encoding=encoding, header=None, names=columns, low_memory=False)
    return _read

def try_and_fix(_read, _ecount):
    '''
    try_and_fix :
    :param _read:
    :param _ecount:
    :return:
    '''
    _error = []
    for item in tqdm(_read.comments):
        try:
            _ecount += 1
            mc.parse(item)
        except:
            _error.append(_ecount)
    for i in range(len(_error)):
        _error[i] = int(_error[i]) - 1
    _read = _read.drop(_error, 0)
    return _read


def fixed_to_nandvs(_read):
    _tmp_list = []
    for item in tqdm(_read.comments):
        try:
            mc.parse(item)
            tmp_str = mc.parse(item)
            _tmp_list.append(parse_Nouns_Vs(tmp_str))
        except:
            pass
    _read.comments = _tmp_list
    return _read


def csv_preprocessing(_process):
    '''

    :param _process:
    :return:
    '''
    num = 0
    tmp_list = []
    if _process == 'error_fix':
        for i in tqdm(range(0, 8)):
            ecount = 0
            num = str(int(num) + 1)  # 파일 여러 개에 일괄 적용하기 위해서 넣은 카운트
            filename = raw_path + str(num) + ".csv"
            filename2 = fixed_path + str(num) + '.csv'

            read = readcsv(filename)
            read = try_and_fix(read, ecount)
            read.to_csv(filename2, encoding='utf-8', header=None, index=False)
    elif _process == 'extract_Nouns&Vs':
        for i in tqdm(range(0, 8)):
            num = str(int(num) + 1) # 파일 여러 개에 일괄 적용하기 위해서 넣은 카운트
            filename2 = fixed_path + str(num) + '.csv'
            filename3 = n_and_v_path + str(num) + '.csv'

            read = readcsv(filename2)
            read = fixed_to_nandvs(read)
            read.to_csv(filename3, encoding='utf-8', header=None, index=False)


def integrate_csv_pickle():
    num = 0
    tmp_list = []
    for i in tqdm(range(0, 8)):
        num = str(int(num) + 1)  # 파일 여러 개에 일괄 적용하기 위해서 넣은 카운트
        filename = n_and_v_path + str(num) + '.csv'
        read = readcsv(filename)
        for i in tqdm(range(0, len(read.comments))):
            tmp_list.append(read.comments[i])
    print(tmp_list)
    with open(list_pickle_path, 'wb') as f:
        pickle.dump(tmp_list, f)


def pickle_to_model(_tmp_list):
    with open(list_pickle_path, 'rb') as f:
        _tmp_list = pickle.load(f)  # 단 한줄씩 읽어옴
    print(_tmp_list)
    # model = Word2Vec(tmp_list, size=100, window=3, min_count=20, workers=50)
    # model.init_sims(replace=True)
    # model.save(md_path)


def plot_2d_graph(vocabs, xs, ys):
    plt.figure(figsize=(8,6))
    plt.scatter(xs, ys, marker ='o')
    for i, v in enumerate(vocabs):
        plt.annotate(v, xy=(xs[i], ys[i]))
    plt.show()


def model_application():
    model = Word2Vec.load(md_path)
    model.most_similar('영화')


def model_configuration():
    font_name = matplotlib.font_manager.FontProperties(
                    fname="C:/Windows/Fonts/gulim.ttc"  # 한글 폰트 위치를 넣어주세요
                ).get_name()
    matplotlib.rc('font', family=font_name)

    model = Word2Vec.load(md_path)
    word_vectors = model.wv
    vocabs = word_vectors.vocab.keys()
    word_vectors_list = [word_vectors[v] for v in vocabs]

    pca = PCA(n_components=2)
    xys = pca.fit_transform(word_vectors_list)
    xs = xys[:, 0]
    ys = xys[:, 1]

    plot_2d_graph(vocabs, xs, ys)


if __name__ == "__main__":
    print('nothingxc')<file_sep>import csv


def save_to_file(comm_info):
    file = open("comm.csv", mode="a+", encoding="euc-kr", newline='')
    writer = csv.writer(file)
    # writer.writerow(['title','score','genre','comment'])
    for comm in comm_info:
        writer.writerow(list(comm.values()))
    return
<file_sep>import requests
from bs4 import BeautifulSoup
import time
from nugu.movie_comment_scrapper.crawling.csv_save import save_to_file
from tqdm import tqdm


def get_last_page(M_ID):
    URL = f"https://movie.naver.com/movie/point/af/list.nhn?st=mcode&sword={M_ID}&target=after"
    # 한줄평 페이지 주소
    result = requests.get(URL)
    soup = BeautifulSoup(result.text, "html.parser")

    pagination = soup.find("div", {"class": "h5_right_txt"})
    if pagination:
        num = pagination.find("strong").string
        max_page = int(num) / 10 + 1
        return int(max_page) # 마지막 페이지 반환
    else:
        return None


def extract_comm(html, title, genre, mid): # 한줄평 1개 추출하는 함수
    comment = html.get_text('|', strip=True).split('|')[3]
    score = html.find("em").string
    return {'mid': mid, 'title': title, 'score': score, 'genre': genre, 'comment': comment}


def extract_comms(last_page, M_ID):
    URL = f"https://movie.naver.com/movie/point/af/list.nhn?st=mcode&sword={M_ID}&target=after"
    # 한줄평 페이지 주소
    comments_info = []
    result = requests.get(URL)
    soup = BeautifulSoup(result.text, "html.parser")
    info = soup.find("div", {"class": "choice_movie_info"})
    title = info.find("h5").get_text(strip=True)
    genre = soup.find("td").get_text(strip=True).split('|')[0]
    for page in range(last_page):
        print(f"Scrapping naver page {page + 1}")
        result = requests.get(f"{URL}&page={page + 1}")
        soup = BeautifulSoup(result.text, "html.parser")
        results = soup.find_all("td", {"class": "title"})
        # print(results[0].get_text(strip=True))
        for result in results:
            # comments['title']=title
            comm = extract_comm(result, title, genre, M_ID) # 한줄평 추출
            # comments.update(extract_comm(result))
            comments_info.append(comm)
        # print(comments_info)
    return comments_info


# extract_comms(1)


def get_movie_comm(i):
    last_page = get_last_page(i) # 마지막 페이지 (페이지 수)
    if last_page is None: #페이지가 없다면
        return None

    if last_page < 120: # 페이지 120 미만까지 추출
        comments = extract_comms(last_page, i)
    else:
        comments = extract_comms(120, i)

    if len(comments) is not 0:
        # print(comments)
        save_to_file(comments) # 파일로 저장
    print(comments)
    return comments
<file_sep>from django.apps import AppConfig


class NuguConfig(AppConfig):
    name = 'nugu'
<file_sep>import requests
from bs4 import BeautifulSoup
import time
from nugu.movie_story_scrapper.crawling.csv_save import save_to_file
from nugu.movie_story_scrapper.crawling.csv2_save import save_to_file2


def get_last_page(M_ID):
    URL = f"https://movie.naver.com/movie/point/af/list.nhn?st=mcode&sword={M_ID}&target=after"
    result = requests.get(URL)
    soup = BeautifulSoup(result.text, "html.parser")

    pagination = soup.find("div", {"class": "h5_right_txt"})
    if pagination:
        num = pagination.find("strong").string
        max_page = int(num) / 10 + 1
        return int(max_page)
    else:
        return None


def extract_comm(html, title, genre, M_ID):
    comment = html.get_text('|', strip=True).split('|')[3]
    score = html.find("em").string
    return {'id': M_ID, 'title': title, 'score': score, 'genre': genre, 'comment': comment}


def extract_summary(M_ID):
    URL = f"https://movie.naver.com/movie/bi/mi/basic.nhn?code={M_ID}"
    # story_info = []
    result = requests.get(URL)
    soup = BeautifulSoup(result.text, "html.parser")
    info = soup.find("div", {"class": "story_area"})
    story = info.find("p").get_text(strip=True)
    return story


def extract_comms(last_page, M_ID):
    # story = extract_summary(M_ID)
    # if story is None:
    #     return
    URL = f"https://movie.naver.com/movie/point/af/list.nhn?st=mcode&sword={M_ID}&target=after"
    comments_info = []
    result = requests.get(URL)
    soup = BeautifulSoup(result.text, "html.parser")
    info = soup.find("div", {"class": "choice_movie_info"})
    title = info.find("h5").get_text(strip=True)
    genre = soup.find("td").get_text(strip=True).split('|')[0]
    if '개봉' in genre:
        return

    for page in range(last_page):
        print(f"Scrapping naver page {page+1}")
        result = requests.get(f"{URL}&page={page+1}")
        soup = BeautifulSoup(result.text, "html.parser")
        results = soup.find_all("td", {"class": "title"})
        # print(results[0].get_text(strip=True))
        for result in results:
            # comments['title']=title
            comm = extract_comm(result, title, genre, M_ID)
            # comments.update(extract_comm(result))
            comments_info.append(comm)
        # print(comments_info)
    return comments_info


# extract_comms(1)


def get_movie_comm(i):
    last_page = get_last_page(i)
    if last_page is None:
        return

    story_info = []
    story = extract_summary(i)

    if story is None:
        return

    story_d = {'id': i, 'story': story}
    story_info.append(story_d)
    save_to_file2(story_info)
    return
    # 밑에는 코멘트 추출하는 코드 동작 시키는 부분
    # if last_page < 120:
    #     comments = extract_comms(last_page, i)
    # else:
    #     comments = extract_comms(120, i)
    #
    # if len(comments) is not 0:
    #     # print(comments)
    #     save_to_file(comments)
    # return comments
<file_sep>'''
영화 줄거리 크롤링 하는 모듈
크롤링 완료 이후에 json파일에 들어가서
파일 제일 마지막 부분 ",}" 에서 ","부분을 지우고 저장할 것
'''

from nugu.movie_story_scrapper.crawling.naver_movie import get_movie_comm as get_comm
import os
import time
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm

with open("comm3.json", mode="a+", encoding="utf-8-sig", newline='') as f:
    f.write('{')
with ThreadPoolExecutor(max_workers=5) as executor:
    for i in range(1, 200000):
        executor.submit(get_comm, i)
# with open("comm3.json", mode="a+", encoding="utf-8-sig", newline='') as f:
#     f.write('}')
content = ''
with open("comm3.json", mode="r", encoding="utf-8-sig", newline='') as f:
    content += f.read()
with open("comm3.json", mode="w", encoding="utf-8-sig", newline='') as f:
    f.write(content[:-1] +"}")<file_sep>#-*- coding: utf-8 -*-
import json
import pickle
# 유사도를 구하기 위한 라이브러리
from numpy import dot
from numpy.linalg import norm
import numpy as np
from datetime import datetime
# import torch


def load_corpus(_string_name):
    '''
    load_corpus : 영화 별 가지는 (명사, 용언으로 구성된) 단어들이 저장된 json파일에서 dict형식으로 갖고옴

    :param _string_name: json형식의 파일
    :return: 영화id를 key로 가지고, 해당 영화의 단어들 리스트를 value로 가지는 dict타입 객체
    '''
    with open(_string_name, 'r', encoding='utf-8-sig') as json_data:
        _corpus = json.load(json_data) # 영화별 단어 다 들고옴
    return _corpus


def avrgvec_to_dict(_corpus, _model, _vector_dict):
    '''
    avrgvec_to_dict : 각 영화에 대해서 단어 벡터들의 평균벡터를 dict형식으로 반환해 주는 모듈

    :param _corpus: 각 영화에 대해 단어들을 가지고 있는 dict타입 객체
    :param _model: 전체 영화의 명사, 용언에 대한 word2vec모델 (gensim Word2vec model)
    :param _vector_dict: 각 영화id에 대해서 해당 영화를 나타내는 벡터를 지니는 dict타입 객체
    :return: 각 영화id에 대해서 해당 영화 벡터를 가지는 dict타입 객체
    '''
    for i, v in _corpus.items(): # 각각의 영화에 대해서
        vector = np.zeros(100) # 먼저 word2vec모델 벡터의 차원이 100차원이므로, 처음에 100차원의 0벡터로 초기화
        count = 0 # 모두 더한 단어의 개수 (나중에 평균 구할 때 count로 나눠 줄 것임)
        for j in _corpus[i]: # 현재 보고 있는 영화에서의 모든 단어에 대해서
            if len(j) == 1: # 만약 단어 크기가 1이라면
                continue # 넘어감
            try:
                temp = _model.wv[j] # 단어 벡터를 갖고옴
                vector += temp # 단어 벡터 더해줌
                count += 1 # 더한 단어 벡터 카운트해준다.
            except:
                pass
        try:
            my_vector = vector / count # 총 합벡터, 합한 벡터 수, 평균벡터
            _vector_dict[i] = my_vector # 각 영화 id를 key로 하고, 영화벡터를 value로 해서 dict에 저장
        except:
            pass
    return _vector_dict


def save_as_pickle(_dict, _string_name):
    '''
    save_as_pickle : 영화 id에 대한 영화 벡터를 지니는 dict타입 객체를 pickle 파일으로 저장하는 모듈

    :param _dict: 영화 id에 대한 영화 벡터를 지니는 dict타입 객체
    :param _string_name: 저장할 파일 이름
    :return: None
    '''
    with open(_string_name + '.bin', 'wb') as f:
        pickle.dump(_dict, f)

def load_from_pickle(_string_name):
    '''
    load_from_pickle : pickle파일에서 영화 id에 대한 영화 벡터를 지니는 dict타입 객체로 반환해주는 모듈

    :param _string_name: pickle 파일 이름
    :return: 영화 id에 대한 영화 벡터를 지니는 dict타입 객체
    '''
    with open(_string_name + '.bin', 'rb') as f:
        _dict = pickle.load(f)
        return _dict


def cos_sim(A, B):
    '''
    cos_sim : 2개의 벡터에 대해서 코사인 유사도를 반환해주는 모듈

    :param A: 영화 벡터 A
    :param B: 영화 벡터 B
    :return: 영화 벡터 A, B사이의 유사도를 구해서 반환해줌
    '''
    # x = torch.Tensor(A)
    # y = torch.Tensor(B)
    # print(x, y)
    return dot(A, B) / (norm(A) * norm(B))

# def get_similarities_from_title(_string_title, _mid_mname, _vector_dict):
#     '''
#     get_similarities_from_title : 영화
#
#     :param _string_title:
#     :param _mid_mname:
#     :param _vector_dict:
#     :return:
#     '''
#     tmp_id = []
#     sim_score = []
#     for k, v in _mid_mname.items():
#         if str(v) == _string_title:
#             tmp_id.append(k)
#
#     if not len(tmp_id) == 0:
#         mid = tmp_id[0]
#         crt_vec = _vector_dict[str(mid)]
#         for key, value in _vector_dict.items():
#             score = cos_sim(crt_vec, value)
#             sim_score.append([key, score])
#         result = sorted(sim_score, key=lambda sim_score: sim_score[1], reverse=True)
#         # result = result[1:11]
#         return result
#     else:
#         print('NO MATCH!')

def get_similarities(_entity, _mid_mname, _vector_dict, is_vector):
    '''
    get_similarities: 영화 줄거리에 대한 유사도를 구해서 반환해주는 함수

    :param _entity: 추천 entity
    :param _mid_mname: {영화 id: 영화 제목} 을 가지는 dict
    :param _vector_dict: { 영화 id: 영화 벡터 } 를 가지는 dict
    :return:
    '''
    mid = -1
    sim_score = {}
    if is_vector: # 유사도 비교할 entity로 벡터가 왔을 때
        crt_vec = _entity
    else: # entity로 벡터가 아닌 영화 제목으로 왔을 때
        tmp_id = []
        print(datetime.now(), '2.1')
        for k, v in _mid_mname.items():
            if str(v) == _entity: # 동일한 제목을 지닌 영화에 대해서
                tmp_id.append(k) # 영화 id를 저장
        print(datetime.now(), '2.2')

        if not len(tmp_id) == 0:
            mid = tmp_id[0] # 제일 처음에 받은 영화 id에 대해서
            try:
                crt_vec = _vector_dict[str(mid)] # 해당 영화의 벡터를 가져온다.
            except:
                return None
        else:
            print('NO MATCH!')
            return None

    print(datetime.now(), '2.2.1')
    for key, value in _vector_dict.items(): # 모든 영화에 대해서
        if key == str(mid): # 동일한 영화는 제외하고
            continue
        score = cos_sim(crt_vec, value) # consine 유사도를 구한다.
        sim_score[key] = score # {영화 id: 유사도} 저장
        # result = result[1:11]
    print(datetime.now(), '2.3')
    return sim_score # {영화 id: 유사도} 를 지니는 dict 반환



def main(entity, is_vector):
    '''
    main: 줄거리에 대한 유사도를 구해서 {영화 id: 유사도} dict를 반환해주는 함수

    :param entity: 영화 추천 entity (개인 벡터, 영화 벡터...)
    :param is_vector: 벡터인지 아닌지 알려주는 flag (True : 벡터, False : String)
    :return: {영화 id: 유사도} dict
    '''
    vector_dict = {}
    corpus_name = 'comm3.json'
    address = 'nugu/movie_story_scrapper/'
    model_name = 'story_20191205_1654' # 모델 이름
    dict_name = 'dict_20191206_1937'
    dict_name_2 = 'dict_mid_mname'

    # 평균 벡터 구해서 딕셔너리 형태로 저장하는 코드
    # 데이터 부족한 영화는 저장하지 않았음 (count가 0)
    # corpus = load_corpus(corpus_name)
    # model = Word2Vec.load(model_name)  # pre-trained된 word2vec 모델 로드함
    # vector_dict = avrgvec_to_dict(corpus, model, vector_dict)
    # save_as_pickle(vector_dict, dict_name)

    vector_dict = load_from_pickle(address + dict_name) # {영화 id: 영화 벡터} dict
    mid_mname = load_from_pickle(address + dict_name_2) # {영화 id: 영화 제목} dict

    sim_result = get_similarities(entity, mid_mname, vector_dict, is_vector) # 줄거리에 대한 유사도를 계산해주는 함수
    # for mid, score in sim_result:
    #     print(mid_mname[int(mid)], score)

    # print(cos_sim(vector_dict['190254'], vector_dict['10001']))

    return sim_result


# if __name__ == "__main__":
#     # main(sys.argv[1], sys.argv[2])
#     main(sys.argv[1], False)
<file_sep>#-*- coding: utf-8 -*-

import pandas as pd
from tqdm import tqdm
from gensim.models.word2vec import Word2Vec
from datetime import datetime

import json
with open('comm3.json', 'r', encoding='utf-8-sig') as json_file:
    json_data = json.load(json_file)

model = Word2Vec(list(json_data.values()), size=100, window=3, min_count=20, workers=50)
model.init_sims(replace=True)
model.save('story_'+str(datetime.now()).replace('-', '').replace(' ', '_').replace(':', '')[:13])
del(json_data)<file_sep>import pandas as pd
from tqdm import tqdm
from gensim.models.word2vec import Word2Vec
from datetime import datetime

num = 0

tmp_list = []
while True:
    dic = {}
    num += 1
    _filename = './comm_n_and_v_utf8_'+str(num)+'_ordered_q.csv'
    encoding = 'utf-8'
    columns = ['mid', 'mname', 'score', 'genre', 'comments']

    try:
        read = pd.read_csv(_filename, encoding=encoding, header=None, names=columns, low_memory=False)
    except:
        break

    for i in tqdm(range(0, len(read.mid))):
        try:
            temp = [x.strip() for x in read.comments[i].split(',')]
            for j in temp:
                if len(j) == 1:
                    temp.remove(j)
            tmp_list.append(temp)
        except:
            pass

model = Word2Vec(tmp_list, size=100, window=3, min_count=20, workers=50)

model.init_sims(replace=True)
model.save('C:/Users/Yeon/PycharmProjects/SAnalysis/movie_comment_scrapper/comm_'+str(datetime.now()).replace('-', '').replace(' ', '_').replace(':', '')[:13])
del(tmp_list)

<file_sep>#-*- coding: utf-8 -*-
import sys
import logging
import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
import pickle
from nugu.movie_story_scrapper.get_recommendations import main as get_story_reco
from nugu.movie_comment_scrapper.get_recommendations import main as get_comm_reco
import pandas as pd
import numpy as np
from datetime import datetime
import json

def get_prsnl_vector(id):
    '''
    get_prsnl_vector: id에 맞는 개인 추천 벡터를 반환해주는 함수

    :param id: user id를 String으로 받음
    :return: user에 대한 개인 추천 벡터를 반환해줌
    '''
    address = 'nugu/movie_story_scrapper/'
    dict_name = 'dict_20191206_1937' # 
    with open(address + dict_name + '.bin', 'rb') as f:
        _dict = pickle.load(f)
    vector = np.zeros(100)
    df = pd.read_csv("nugu/user_log.csv") # id, mid, time으로 구성되어 있음
    count = 0
    for i in range(len(df)): # 모든 user log에 대해서
        if str(df['id'][i]) == id: # 현재 user id에 대한 log라면
            try:
                vector += _dict[str(df['mid'][i])] # 해당 mid를 가지는 영화 벡터를 더해준다.
                count += 1
            except:
                continue
    if count != 0:
        vector = list(np.dot(vector, 1/count)) # 그리고 영화 벡터들의 평균을 구해준다.
    return vector # 그리고 이를 개인 영화 추천 벡터로 삼아 반환해준다.


def get_reco(entity, is_vector, n):
    '''
    get_reco: 추천 알고리즘을 통해서 Top N개의 영화를 추천해주는 함수

    :param entity: 유저가 추천 요청을 한 entity (영화 벡터, 개인 벡터, 장르)
    :param is_vector: 들어온 entity가 벡터 형식인지 아닌지 표시해 주는 flag
    :param n: 추천할 n개의 영화
    :return: 유사도 높은 n개의 영화 제목을 지닌 리스트 반환
    '''
    w_story = 0.4 # 줄거리 유사도에 대한 가중치
    w_comment = 0.6 # 한줄평 유사도에 대한 가중치

    story_sim = get_story_reco(entity, is_vector) # 줄거리에 대한 {영화id: 유사도} 형태의 dict 반환
    comment_sim = get_comm_reco(entity, is_vector) # 한줄평에 대한 {영화id: 유사도} 형태의 dict 반환

    with open('nugu/dict_mid_mname.bin', 'rb') as f: # {영화 id : 영화 제목} 형태의 dict
        ID_dict = pickle.load(f)

    entire_sim = [] # 가중치 계산을 통한 최종 유사도를 저장할 리스트
    try:
        for k, v in comment_sim.items():
            try:
                sim = (w_story * story_sim[k]) + (w_comment * v) # 줄거리 가중치 * 줄거리 유사도 + 한줄평 가중치 *  한줄평 유사도 = 최종 유사도
                entire_sim.append((sim, k))
            except:
                continue
    except:
        return []
    entire_sim.sort(reverse=True) # 유사도 높은 순으로 정렬
    print([(ID_dict[int(x[1])], x[0]) for x in entire_sim[:n]])
    return [ID_dict[int(x[1])] for x in entire_sim[:n]] # 유사도 높은 순으로 영화 제목 n개 반환


def get_reco2(prsnl_vector, reco_entity, include_genre, n):
    '''
    get_reco2: 개인 영화 추천, 장르 추천을 해주는 함수

    :param prsnl_vector: 개인 추천 벡터 (유저의 시청 기록을 토대로 생성된 벡터)
    :param reco_entity: 장르 추천의 경우 장르 이름이 넘어온다. ex) 공포, 드라마, 로맨스, ...
    :param include_genre: 장르 추천인지 아닌지(개인 영화 추천) 판단해주는 (True: 장르 추천, False: 개인 추천)
    :param n: 추천할 n개의 영화
    :return: 유사도 높은 n개의 영화 제목을 지닌 리스트 반환
    '''

    w_story = 0.4 # 줄거리 유사도에 대한 가중치
    w_comment = 0.6 # 한줄평 유사도에 대한 가중치

    story_sim = get_story_reco(prsnl_vector, True) # 개인 추천 벡터에 대해서 줄거리에 대한 {영화id: 유사도} 형태의 dict 반환
    comment_sim = get_comm_reco(prsnl_vector, True) # 개인 추천 벡터에 대해서 한줄평에 대한 {영화id: 유사도} 형태의 dict 반환

    with open('nugu/dict_mid_mname.bin', 'rb') as f: # {영화 id : 영화 제목} 형태의 dict
        ID_dict = pickle.load(f)

    with open('nugu/dict_mid_genre_real_eincluded_1212.bin', 'rb') as f: # {영화 id : [장르]} 형태의 dict
        mid_genre_dict = pickle.load(f)

    entire_sim = [] # 가중치 계산을 통한 최종 유사도를 저장할 리스트
    try:
        for k, v in comment_sim.items():
            try:
                sim = (w_story * story_sim[k]) + (w_comment * v) # 줄거리 가중치 * 줄거리 유사도 + 한줄평 가중치 *  한줄평 유사도 = 최종 유사도
                entire_sim.append((sim, k))
            except:
                continue
    except:
        return []
    entire_sim.sort(reverse=True) # 유사도 높은 순으로 정렬
    if not include_genre: # 만약 개인 추천 요청이라면
        return [ID_dict[int(x[1])] for x in entire_sim[:n]] # 유사도 높은 순으로 영화 제목 n개 반환

    # 장르 추천
    new_sim = entire_sim[:1000] # 개인 추천 벡터와 유사한 1000개의 영화들을 뽑아냄.
    count = 0
    count_list = []
    temp_list = []
    for x in new_sim: # 유사한 1000개의 영화들 중에서
        count = count + 1
        if reco_entity in mid_genre_dict[int(x[1])]: # 유저가 원하는 장르를 가지고 있는 영화를 따로 저장
            temp_list.append(x)
    for item in count_list:
        del new_sim[int(item)]
    return [ID_dict[int(x[1])] for x in temp_list[:n]] # 유사도 높은 순으로 영화 제목 n개 반환


def main(reco_num, reco_entity):
    '''
    main: 추천도가 높은 영화 제목들을 반환해주는 함수
    :param reco_num: 추천 종류 (1: 개인 추천, 2: 장르 추천, 3: 유사 영화 추천)
    :param reco_entity: user가 원하는 추천에 대한 entity
    :return: 추천도에 따른 영화 제목 반환해주는 리스트
    '''
    n = 10 # 추천받을 영화 개수

    if reco_num == '1':  # 개인 추천

        # with open(address + dict_name + '.bin', 'rb') as f:
        #     _dict = pickle.load(f)
        # prsnl_vector = _dict['10001']  # 시네마 천국이 일단은 벡터값으로 들어가게 된다
        prsnl_vector = get_prsnl_vector(reco_entity) #
        return get_reco2(prsnl_vector, reco_entity, False, n)

    elif reco_num == '2':  # 장르 추천
        prsnl_vector = get_prsnl_vector(reco_entity)
        print(prsnl_vector)
        return get_reco2(prsnl_vector, reco_entity, True, n)

    elif reco_num == '3':  # 유사 영화 추천
        return get_reco(reco_entity, False, n)
    else:
        logging.info("잘못된 입력입니다. 1.개인추천 2.장르추천 3.유사영화추천")
    return None


# if __name__ == "__main__":
#     '''
#     python get_recommendations.py {arg 1} {arg 2}
#     [arg 1 : 추천 종류]
#     개인추천 : 1
#     장르추천 : 2
#     유사영화추천 : 3
#
#     [arg 2 : 추천 entity]
#     개인추천 ex) '해당 사람의 ID'
#     장르추천 ex) '공포', '드라마', '스릴러', '액션', ...
#     유사영화추천 ex) '신과함께', '명량', ...
#     '''
#     print(main(sys.argv[1], sys.argv[2]))



<file_sep>from gensim.models.word2vec import Word2Vec
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
import matplotlib

font_name = matplotlib.font_manager.FontProperties(
                fname="C:/Windows/Fonts/gulim.ttc"  # 한글 폰트 위치를 넣어주세요
            ).get_name()
matplotlib.rc('font', family=font_name)

def plot_2d_graph(vocabs, xs, ys): 
    plt.figure(figsize=(8,6))
    plt.scatter(xs, ys, marker ='o')
    for i, v in enumerate(vocabs):
        plt.annotate(v, xy=(xs[i], ys[i]))
    plt.show()

model = Word2Vec.load('../20191124_0200')



word_vectors = model.wv

print(model.wv['김혜수'])
print(model.wv.most_similar('욕정'))
print(model.wv.most_similar('재미'))
print(model.wv.most_similar('재밌'))
print(model.most_similar(positive=['김혜수', '레이첼'], negative=['여자', '여배우'],  topn=10))
vocabs = word_vectors.vocab.keys()
word_vectors_list = [word_vectors[v] for v in vocabs]

# pca = PCA(n_components=2)
# xys = pca.fit_transform(word_vectors_list)
# xs = xys[:, 0]
# ys = xys[:, 1]
#
#plot_2d_graph(vocabs, xs, ys)





# from sklearn.decomposition import IncrementalPCA    # inital reduction
# from sklearn.manifold import TSNE                   # final reduction
# import numpy as np                                  # array handling
# from gensim.models.word2vec import Word2Vec
# import matplotlib.pyplot as plt
# from sklearn.decomposition import PCA
# import matplotlib
# from plotly.offline import init_notebook_mode, iplot, plot
# import plotly.graph_objs as go
# import random
#
# font_name = matplotlib.font_manager.FontProperties(
#                 fname="C:/Windows/Fonts/gulim.ttc"  # 한글 폰트 위치를 넣어주세요
#             ).get_name()
# matplotlib.rc('font', family=font_name)
# model = Word2Vec.load('20191123_2300')
#
# def reduce_dimensions(model):
#     num_dimensions = 2  # final num dimensions (2D, 3D, etc)
#
#     vectors = [] # positions in vector space
#     labels = [] # keep track of words to label our data again later
#     for word in model.wv.vocab:
#         vectors.append(model.wv[word])
#         labels.append(word)
#
#     # convert both lists into numpy vectors for reduction
#     vectors = np.asarray(vectors)
#     labels = np.asarray(labels)
#
#     # reduce using t-SNE
#     vectors = np.asarray(vectors)
#     tsne = TSNE(n_components=num_dimensions, random_state=0)
#     vectors = tsne.fit_transform(vectors)
#
#     x_vals = [v[0] for v in vectors]
#     y_vals = [v[1] for v in vectors]
#     return x_vals, y_vals, labels
#
#
# x_vals, y_vals, labels = reduce_dimensions(model)
#
# def plot_with_plotly(x_vals, y_vals, labels, plot_in_notebook=True):
#
#     trace = go.Scatter(x=x_vals, y=y_vals, mode='text', text=labels)
#     data = [trace]
#
#     if plot_in_notebook:
#         init_notebook_mode(connected=True)
#         iplot(data, filename='word-embedding-plot')
#     else:
#         plot(data, filename='word-embedding-plot.html')
#
#
# def plot_with_matplotlib(x_vals, y_vals, labels):
#
#     random.seed(0)
#
#     plt.figure(figsize=(12, 12))
#     plt.scatter(x_vals, y_vals)
#
#     #
#     # Label randomly subsampled 25 data points
#     #
#     indices = list(range(len(labels)))
#     selected_indices = random.sample(indices, 25)
#     for i in selected_indices:
#         plt.annotate(labels[i], (x_vals[i], y_vals[i]))
#     plt.show()
#
# try:
#     get_ipython()
# except Exception:
#     plot_function = plot_with_matplotlib
# else:
#     plot_function = plot_with_plotly
#
# plot_function(x_vals, y_vals, labels)<file_sep>#-*- coding: utf-8 -*-

import re
import MeCab
from datetime import datetime

def save_to_file2(comm_info):
    m = MeCab.Tagger()
    with open("comm3.json", mode="a+", encoding="utf-8-sig", newline='') as f:
        word_list = []
        tagged_str = m.parse(comm_info[0]['story'])
        tagged_str = list(re.split('\t|\n',tagged_str))
        for i in range(1, len(tagged_str), 2):
            if tagged_str[i].startswith('NN') or tagged_str[i].startswith('V'):  # 명사와 용언으로 된 것을 뽑아낸다
                word_list.append(tagged_str[i - 1])
        temp = str({str(comm_info[0]['id']) : word_list}).replace("'", '\"')
        f.write(temp[1:-1]+', ')
    if comm_info[0]['id'] % 2000 == 0:
        print("current id : {}, {}% completed, time : {}".format(comm_info[0]['id'], int(comm_info[0]['id']/2000), datetime.now()))
    return
