def each_sentence_division(script_string_array): # 한 문장 단위로 끊어서 분석하는 함수 global element_table mecab = Mecab() string_table = [] count = 0 for each in script_string_array: # 문장 단위로 끊어져 저장되어 있는 배열에서 한 문장씩 (each) 형태소 분석 complete_sentence = [] sentence = str(each) sentence = remove_marks(sentence) #특수문자 제거 sentence = add_space_after_mot(sentence) # '못' 띄어쓰기 처리 mecab_result = mecab.pos(sentence) for i in range(len(mecab_result)): complete_sentence.append(mecab_result[i]) string_table.append(complete_sentence) # 분석 완료된 문장을 string_table에 추가 #element_table, modifier_table 구성하는 작업 one_line_temp = make_element_table(complete_sentence, script_string_array[count]) element_table = np.append(element_table, np.array([one_line_temp], dtype=list), axis=0) modifier_table.append( make_modifier_table(script_string_array[count], complete_sentence)) count += 1
def write_corpora(sentences, output_file_handle, min_token_count=5, tagger=None, isAllTag=False): if tagger is None: tagger = Mecab() target_tags = get_tags(tagger, isAllTag) for i, s in enumerate(sentences): try: pos_tagged = tagger.pos(s) except ValueError: print(f'could not {i}th parsed! sentence = {s}') continue if len(target_tags) == 0: tokenized = [t[0].strip() for t in pos_tagged] else: tokenized = [ t[0].strip() for t in pos_tagged if t[1] in target_tags ] if len(tokenized) < min_token_count: continue output_file_handle.write(' '.join(tokenized) + '\n')
def sentence_division(input_string): global element_table mecab = Mecab() input_string = add_space_after_mot(input_string) # '못' 뒤에 띄어쓰기 추가 string_table = [] # 한 문장씩 저장할 테이블 mecab_result = mecab.pos( input_string) # ex) [('안녕', 'NNG'), ('하', 'XSV'), ('세요', 'EP+EF')] string_start = 0 # 각 문장의 첫번째 요소 가르키는 변수 cnt = 0 # 한 문장에 대해 형태소 분석이 안 된 문장을 index로 찾아가기 위한 변수 for i in range(len(mecab_result)): if is_sentence_End(mecab_result[i]): # 문장의 마지막인지 판단 sentence = [] for j in range(string_start, i + 1): # 한 문장 내의 첫번째 요소부터 마지막 요소까지 저장. # if is_MAG_except_neg(mecab_result[j]): # '못', '안'을 제외한 MAG[일반 부사]는 저장 X # continue if is_mark(mecab_result[j]): # 문장부호는 저장 X continue sentence.append(mecab_result[j]) # 각 요소를 현재 문장에 추가 string_table.append(sentence) # 완성된 한 문장을 테이블에 추가 cnt += 1 string_start = i + 1 # 다음 문장의 첫 번째 요소를 가리킴. return string_table
def get_corpora(sentences, tagger=None, isAllTag=False): if tagger is None: tagger = Mecab() # 모든 형태소 대상이면 비어있는 배열 target_tags = get_tags(tagger, isAllTag) corporas = [] for i, s in enumerate(sentences): try: pos_tagged = tagger.pos(s) except ValueError: print(f'could not {i}th parsed! sentence = {s}') continue if len(target_tags) == 0: tokenized = [t[0].strip() for t in pos_tagged] else: tokenized = [ t[0].strip() for t in pos_tagged if t[1] in target_tags ] corporas.append(' '.join(tokenized)) return corporas
def embed(data): mecab = Mecab() inputs = [] labels = [] for encode_raw in data['encode']: encode_raw = mecab.morphs(encode_raw) encode_raw = list( map(lambda x: encode_raw[x] if x < len(encode_raw) else '#', range(encode_length))) if (embed_type == 'onehot'): bucket = np.zeros(vector_size, dtype=float).copy() input = np.array( list( map( lambda x: onehot_vectorize(bucket, x) if x in model.wv.index2word else np.zeros(vector_size, dtype=float), encode_raw))) else: input = np.array( list( map( lambda x: model[x] if x in model.wv.index2word else np. zeros(vector_size, dtype=float), encode_raw))) inputs.append(input.flatten()) for decode_raw in data['decode']: label = np.zeros(label_size, dtype=float) np.put(label, decode_raw, 1) labels.append(label) return inputs, labels
def __init__(self, pred_config: Pred_config, task_id=None, keyword=None, channel=None): self.pred_config = pred_config self.engine = create_engine( ("mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8mb4").format( 'root', 'robot369', '10.96.5.179', 3306, 'datacast2')) self.args = self.pred_config.get_args() ##쿠다, cpu 중 사용할 디바이스 설정 self.device = self.pred_config.get_device() ##배치사이즈 설정(모델이 한번에 처리할 input 사이즈 크기) self.batch_size = self.pred_config.batch_size ##모델 가져오기 self.model = self.pred_config.load_model(self.args, self.device) ##토크나이저 가져오기 self.tokenizer = self.pred_config.load_tokenizer() self.nlp = Mecab() self.task_id = task_id self.keyword = keyword self.channel = channel
def generate_from_text(self, text): """Generate wordcloud from text. The input "text" is expected to be a natural text. If you pass a sorted list of words, words will appear in your output twice. To remove this duplication, set ``collocations=False``. Calls process_text and generate_from_frequencies. ..versionchanged:: 1.2.2 Argument of generate_from_frequencies() is not return of process_text() any more. Returns ------- self """ if self.korean: try: from eunjeon import Mecab except ImportError: raise Exception("Please install pyeunjeon properly. https://github.com/koshort/pyeunjeon") tagger = Mecab() words = Counter(tagger.nouns(text)) else: words = self.process_text(text) self.generate_from_frequencies(words) return self
def dataPrePrcs(contents): no_kor_num = 0 logger = __get_logger() try: logger.info('mecab 형태소 분석기를 실행합니다.') tagger = Mecab() except Exception as e: trace_back = traceback.format_exc() message = str(e) #+"\n"+ str(trace_back) logger.error('mecab형태소 분석기 실행에 실패하였습니다. %s', message) #sys.exit() try: logger.info('한글 외의 글자를 삭제합니다.') hangul = re.compile('[^ ㄱ-ㅣ가-힣]+') for j in range(len(contents)): if re.match('[^ ㄱ-ㅣ가-힣]+', str(contents[j])): no_kor_num += 1 contents = [ hangul.sub('', str(contents[cn])) for cn in range(len(contents)) ] logger.info('한글 외의 글자를 가진', no_kor_num, '개의 문서 삭제를 완료했습니다.') except Exception as e: trace_back = traceback.format_exc() message = str(e) #+"\n"+ str(trace_back) logger.error('한글 외의 글자 삭제에 실패하였습니다.. %s', message) #sys.exit() try: logger.info('각 문서의 명사를 추출합니다.') tokenized_doc = [] for cnt in tqdm(range(len(contents))): nouns = tagger.nouns(contents[cnt]) tokenized_doc.append(nouns) logger.info('각 문서의 명사추출을 완료했습니다.') except Exception as e: trace_back = traceback.format_exc() message = str(e) #+"\n"+ str(trace_back) logger.error('각 문서의 명사를 추출에 실패하였습니다.. %s', message) #sys.exit() # 한글자 단어들 지우기! try: logger.info('한 글자 단어를 삭제합니다.') num_doc = len(tokenized_doc) one_word = 0 for i in range(num_doc): tokenized_doc[i] = [ word for word in tokenized_doc[i] if len(word) > 1 ] logger.info("한 글자 단어를 삭제를 완료했습니다.") except Exception as e: trace_back = traceback.format_exc() message = str(e) #+"\n"+ str(trace_back) logger.error('한 글자 단어를 삭제에 실패하였습니다.. %s', message) #sys.exit() return tokenized_doc
def write_corpora(sentences, output_file_handle, tagger=None): target_tags = None if tagger is None: tagger = Mecab() if isinstance(tagger, konlpy.tag._okt.Okt): target_tags = ['Alpha', 'Noun', 'Adjective'] elif isinstance(tagger, konlpy.tag._kkma.Kkma): target_tags = ['NN', 'NNG', 'NNB', 'NNM',' NNP', 'NP', 'NR', 'OH', 'OL', 'ON', 'VA', 'VXA'] elif isinstance(tagger, konlpy.tag._komoran.Komoran): target_tags = ['NNG', 'NNB', 'NNP', 'NP', 'NR', 'SH', 'SL', 'SN', 'VA'] elif isinstance(tagger, eunjeon._mecab.Mecab): target_tags = ['VA', 'NNG', 'NNB', 'NNBC', 'NNP', 'NP', 'NR', 'SH', 'SL', 'SN', 'VA'] else: raise ValueError(f'invalid tagger {tagger.__class__}') for i, s in enumerate(sentences): try: pos_tagged = tagger.pos(s) except ValueError: print(f'could not {i}th parsed! sentence = {s}') continue tokenized = [t[0].strip() for t in pos_tagged if t[1] in target_tags] output_file_handle.write(' '.join(tokenized) + '\n')
def clean_korean_documents_simple_version(documents): #텍스트 정제 (HTML 태그 제거) for i, document in enumerate(documents): document = BeautifulSoup(document, 'html.parser').text #print(document) #스토리가 진짜 너무 노잼 documents[i] = document #텍스트 정제 (특수기호 제거) for i, document in enumerate(documents): document = re.sub(r'[^ ㄱ-ㅣ가-힣]', '', document) #특수기호 제거, 정규 표현식 #print(document) stale and uninspired documents[i] = document #텍스트 정제 (형태소 추출) for i, document in enumerate(documents): eunjeon = Mecab() clean_words = [] for word in eunjeon.morphs(document): clean_words.append(word) #print(clean_words) #['스토리', '진짜', '노잼'] document = ' '.join(clean_words) #print(document) #스토리 진짜 노잼 documents[i] = document return documents
def validate(msg): # print(len(msg.split())) # if len(msg.split()) == 1: # return ['PASS', 'ONEWORD', ""] """' eunjeon.Mecab 를 이용해 입력받은 문장의 축을 이루는 명사+동사의 개수가 전체 형태소의 개수보다 많을 경우wordpop() 함수롤 실행시킴. 입력값에 대하여 선택적으로 봇이 답변하도록 하여 채팅창 도배를막음. """ tagger = Mecab('/usr/local/lib/mecab/dic/mecab-ko-dic') Pos = tagger.pos(msg) numWord = 0 # 동사개수 - 형태소 분리 후 VV 개수로 파악. realword = [] # 실제 의미를 가지는 단어들 target = [ "NNG", "NNP", "NNB", "NNBC", "NP", "VV", "VA", "VX", "XSV", "XR", "MAG", "IC" ] # POS tag chart : https://bit.ly/2KOA1ua for i in Pos: if i[1] in target: print(i[0]) numWord += 1 realword.append(i[0]) # 실제 의미를 가지는 단어들만 전달되도록 필터링함. if Pos[-1][1] == "SF": # 문장부호는 맨 마지막에 한번만 붙이도록. realword.append(Pos[-1][0]) numPos = len(Pos) # 전체 형태소의 개수 print(Pos) print(numWord, numPos - numWord) if numWord >= (numPos - numWord): # 의미를 가지는 요소가 문장의 과반 이상일 경우(비율은 수정가능) return wordpop(realword) else: return ["PASS", numWord, numPos]
def predict_(request): if request.method == "GET": start = time.time() review = request.GET["review"] print("Get Review _________________________________") pkl = joblib.load('./restapi/reviewSentiment.pkl') model = FastText.load('./restapi/FastText_embedding.model').wv print("load Model __________________________________") okt = Mecab() review_text = re.sub review_text = re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ\\s]", "", review) word_review = okt.morphs(review_text) word_review = ' '.join(word_review) print("preprocessing _______________________") feature_vector = np.zeros((100), dtype=np.float32) num_words = 0 index2word_set = set(model.wv.index2word) for w in word_review.split(): if w in index2word_set: num_words += 1 feature_vector = np.add(feature_vector, model.wv[w]) feature_vector = np.divide(feature_vector, num_words) print("predict _____________________________________") result = pkl.predict([feature_vector]) print("time :", time.time() - start) # 현재시각 - 시작시간 = 실행 시간 if result[0] == 1: return redirect('emotion/1') else: return redirect('emotion/0')
def mecabFreqToDataFrame(text): mecab = Mecab() # kkma.nouns(text)라는 함수가 있지만 결과가 좋지 못하므로 조건을 달리함 nouns = mecab.nouns(text) # 각 명사의 숫자 세기 count = Counter(nouns) tag_count = [] tags = [] # 가장 많이 카운팅된 명사를 차례로 tags와 tag_count리스트에 추가 for n, c in count.most_common(100): dics = {'tag': n, 'count': c} # 글자 수 조건 2~49자 if len(dics['tag']) >= 2 and len(tags) <= 49: tag_count.append(dics['count']) tags.append(dics['tag']) # 어떤 텍스트가 형태소 분리됬는지 디버깅 joined_text = " ".join(tags) print("형태소 : ", joined_text) print("언어 감지됨 : ", detect_langs(joined_text)) # 본문 토큰화 시킨 것을 데이터프레임으로 변환 return pd.DataFrame({"Word": list(tags), "Frequency": list(tag_count)})
def ajax_news_analysis(request): news_data = json.loads(request.POST.get('news_data', '')) mecab = Mecab() def sentiment_predict(new_sentence): max_len = 30 stopwords = [ '의', '가', '이', '은', '들', '는', '좀', '잘', '걍', '과', '도', '를', '으로', '자', '에', '와', '한', '하다' ] new_sentence = re.sub(r'[^ㄱ-ㅎㅏ-ㅣ가-힣 ]', '', new_sentence) new_sentence = mecab.morphs(new_sentence) # 토큰화 new_sentence = [ word for word in new_sentence if not word in stopwords ] # 불용어 제거 #tokenizer = Tokenizer() tokenizer.fit_on_texts([new_sentence]) encoded = tokenizer.texts_to_sequences([new_sentence]) # 정수 인코딩 pad_new = pad_sequences(encoded, maxlen=max_len) # 패딩 score = float(loaded_model.predict(pad_new)) # 예측 return score * 100 score = [] words_list = [] for i in range(len(news_data['items'])): title = news_data['items'][i]['title'] words_list.extend(mecab.nouns(title)) s = sentiment_predict(title) if s > 10 and s < 90: score.append(s) score_avg = sum(score) / len(score) counter = collections.Counter(words_list) data = {'LSTM_sent': score_avg, 'words_list': counter.most_common(30)} return JsonResponse(data, safe=False)
def isAfterNoun(self, rp): if rp == '': return True m = Mecab() # m = Mecab(dicpath='C:/mecab/mecab-ko-dic') # (사용불가능, 비활성) # m = Mecab(dicpath='/usr/local/lib/mecab/dic/mecab-ko-dic') # (사용불가능, 비활성) if m.pos(rp)[0][1][0] in ['N', 'V', 'J', 'E', 'X']: return True return False
def krword_tokenize(sent): result = [] mecab = Mecab() sample = mecab.pos(sent) for x in sample: if 'NNG' in x or 'NNP' in x or 'NNB' in x or 'NP' in x: result.append(x) return result
def nounExt(self, sentlist): m = Mecab() # m = Mecab(dicpath='C:/mecab/mecab-ko-dic') # (사용불가능, 비활성) # m = Mecab(dicpath='/usr/local/lib/mecab/dic/mecab-ko-dic') # (사용불가능, 비활성) out = [] for i in sentlist: out.append(m.nouns(i)) return out
def concat_text_with_pos(setence): tag = Mecab() pos = tag.pos(setence) temp = [] for p in pos: temp.append(p[0] + "/" + p[1]) s = ' '.join(temp) return s
def lematization(self, texts): #['NOUN', 'ADJ', 'VERB', 'ADV'] print(' ...Make lematization...') texts_out = [] mecab = Mecab() for sent in tqdm(texts): sent = ' '.join(sent) sent = mecab.nouns(sent) texts_out.append(sent) return texts_out
def onlyNouns(article): result = "" mecab = Mecab() sample = mecab.pos(article) for x in sample: if 'NNG' in x or 'NNP' in x or 'NNB' in x or 'NP' in x: result += (x[0]) + ' ' # print(result) return result
def get_raw_sentence(path): mecab = Mecab() with open(path, 'r', encoding='utf-8-sig') as f: sentences = f.readlines() sentences = list(map(make_raw_sentence, sentences)) mecab.morphs() sentences = [sentence.strip() for sentence in sentences] return sentences
def hello(): app = Flask(__name__) app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True contents = "ndllocvcv" from konlpy.tag import Mecab tagger = Mecab() t = tagger.pos("고양이는 양옹뉴턴야옹") print("========================================") return json.dumps(t, ensure_ascii=False)
def do_mecab(text): mecab = Mecab() me_list = mecab.pos(text) after = [] for t in me_list: if t[1][0] == 'N' or t[1][0] == 'V': #s랑 m도 더함 after.append(t) print(after) return me_list
def tokenize_mecab(docs_list): from eunjeon import Mecab m = Mecab(dicpath='/usr/local/lib/mecab/dic/mecab-ko-dic') token_list = [] for i in tqdm(range(len(docs_list)), desc='Tokenizing docs'): nouns = [ t[0] for t in m.pos(docs_list[i]) if (t[1] in ['NNG', 'NNP']) and (len(t[0]) > 1) ] token_list.append(nouns) return token_list
def extract_nouns_v2(news: str) -> dict: """Extract nouns from news. :param news: contents of news. :return: dict(). Extracted keyword and its count. {keyword: count, } """ mecab = Mecab() news_lines = kss.split_sentences(news) nouns = [] for line in news_lines: nn = 0 pos = 0 for token in mecab.pos(line): pos = pos + line[pos:].find(token[0]) if token[1] == 'NNG': # 일반 명사 if nn > 0: if line[pos - 1] == ' ': nouns.append( (f'{nouns[-1][0]} {token[0]}', nouns[-1][1])) nouns.append(token[0]) else: nouns[-1] = (f'{nouns[-1][0]}{token[0]}', nouns[-1][1]) nn += 1 else: nn = 1 nouns.append(token) elif token[1] == 'NNP': # 고유 명사 if nn > 0: if line[pos - 1] == ' ': nouns.append((f'{nouns[-1][0]} {token[0]}', 'NNP')) nouns.append(token[0]) else: nouns[-1] = (f'{nouns[-1][0]}{token[0]}', 'NNP') nn += 2 else: nn = 2 nouns.append(token) else: nn = 0 pos += len(token[0]) return dict(Counter(nouns))
def make_keyword(sample_data): ''' :param sample_data: DataFrame :return: content column의 내용 토큰화-> 상위 10개 키워드 리스트 반환 ''' # 불용어 정의 stopwords = ['어때','아하','어때요','니깐','니까','거든','을까','할까','거든요','많이','조금','습니당','습니다','입니다','니다','여러분','라도','만나','어디', '이렇게','저렇게','은데','한데','응','아직','응응','그래','오키','든요','어떻게','왜','감사','고맙','죄송','랑','이랑','지만','하지만', '화이팅','파이팅','습니다','슴당','아요','에요','예요','아용','가용','바로','그냥','수정','파일','보내','올려','이모티콘', '따로', '다고', '구나', 'ㅠㅠㅠㅠ', 'ㅠㅠㅠ', '잖아', '그거', '부분', '어제', '내일', '오늘', '을까요', '괜찮', '으면', '해야', 'ㅇㅋ', '각자', '이건', '이거', '상관없', '사진', '께서', '드릴게요', '오후', '오전', '우선', '걸로', '이번', '해도', '할까요', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일', '일요일', '까지', '드려요', '너무', '해요', '네네', '오늘', '다음', '아서', '셔서', '올리', '진짜', '오빠', '누나', '언니', '의', '가', '이', '은', '들', '는', '좀', '잘', '걍', '과', '도', '를', '으로', '자', '에', '와', '한', '하다', '다', '고', '을', '하', '있', '게', '보', '없', '세요', '아요', '습니다', '이', '있', '하', '것', '들', '그', '되', '수', '이', '보', '않', '없', '나', '사람', '주', '아니', '등', '같', '우리', '때', '년', '가', '한', '지', '어요', '네요', '대하', '오', '말', '일', '그렇', '이나', '위하', '는데', '있', '하', '것', '들', '그', '되', '수', '이', '보', '않', '없', '나', '사람', '주', '아니', '등', '같', '우리', '때', '년', '가', '한', '지', '대하', '오', '말', '일', '그렇', '위하', '때문', '그것', '두', '말하', '알', '그러나', '받', '못하', '일', '그런', '또', '문제', '더', '사회', '많', '그리고', '좋', '크', '따르', '중', '나오', '가지', '씨', '시키', '만들', '지금', '생각하', '그러', '속', '하나', '집', '살', '모르', '적', '월', '데', '자신', '안', '어떤', '내', '내', '경우', '명', '생각', '시간', '그녀', '다시', '이런', '앞', '보이', '번', '나', '다른', '어떻', '여자', '개', '전', '들', '사실', '이렇', '점', '싶', '말', '정도', '좀', '원', '잘', '통하', '소리', '놓', '그럼', '혹시', '니다', '에서', '아침', '점심', '저녁', '해서', '어서', '감사', '수고', '저희', '근데', '일단', '나요', '부터', '합니다', '니까', '안녕', '입니다'] file_extension_list=make_file_extension_list("resource\\filename_extension_list.txt") for extension in file_extension_list: x=extension.replace(".","") stopwords.append(x) # 토큰화 및 불용어 제거 tokenizer = Mecab() tokenized = [] for sentence in sample_data['Content']: temp = tokenizer.morphs(sentence) # 토큰화 temp = [word for word in temp if not word in stopwords] # 불용어 제거 temp = [word for word in temp if len(word) > 1] tokenized.append(temp) # 전처리한 단어 데이터 데이터 프레임 구조로 변환 vocab = FreqDist(np.hstack(tokenized)) vocab = pd.DataFrame(vocab, {'count': [1]}) vocab = vocab.transpose() vocab = vocab.sort_values(by='count', ascending=False) vocab.reset_index(inplace=True) # 상위 언급 10개 단어 추출 dataf_10 = vocab.iloc[0:10] dataf_10 = dataf_10.reset_index() data10_dic = dataf_10['index'] data10_dic = pd.Series(data10_dic) data10_list = list(data10_dic) print("키워드 추출완료\n") return data10_list,vocab
def train_vector_model(str_buf): mecab = Mecab() str_buf = train_data_list['encode'] pos1 = mecab.pos(''.join(str_buf)) pos2 = ' '.join(list(map(lambda x: '\n' if x[1] in ['SF'] else x[0], pos1))).split('\n') morphs = list(map(lambda x: mecab.morphs(x), pos2)) print(str_buf) model = word2vec.Word2Vec(size=vector_size, window=2, min_count=1) model.build_vocab(morphs) model.train(morphs, epochs=model.epochs, total_examples=model.corpus_count) return model
def isKnown(self, text): if len(text) == 0: return True m = Mecab() # m = Mecab(dicpath='C:/mecab/mecab-ko-dic') # (사용불가능, 비활성) # m = Mecab(dicpath='/usr/local/lib/mecab/dic/mecab-ko-dic') # (사용불가능, 비활성) for i in m.morphs(text): if m.pos( i )[0][1] == 'UNKNOWN': # or maybe include when first letter is 'S' too? # print(i) # it is not RP return False return True
def train_vector_model(str_buf): mecab = Mecab() str_buf = train_data_list['encode'] #mecab로 POS Tagging pos1 = mecab.pos(''.join(str_buf)) #문장별로 list로 나눔 마침표등이 존재시 줄바꾸기 (문장이길경우) pos2 = ' '.join(list(map(lambda x: '\n' if x[1] in ['SF'] else x[0], pos1))).split('\n') #단어구성을 위한 형태소단위 문장 쪼개기 morphs = list(map(lambda x: mecab.morphs(x), pos2)) model = word2vec.Word2Vec(size=vector_size, window=2, min_count=1) model.build_vocab(morphs) model.train(morphs, total_examples=model.corpus_count, epochs=model.iter) return model
def splitEojeol(self, eojeol): out = [] m = Mecab() # m = Mecab(dicpath='C:/mecab/mecab-ko-dic') # (사용불가능, 비활성) # m = Mecab(dicpath='/usr/local/lib/mecab/dic/mecab-ko-dic') # (사용불가능, 비활성) if eojeol[-1] == '.': eojeol = eojeol[:-1] for i in range(len(eojeol)): for j in range(len(eojeol) - i): k = eojeol[i:j + i + 1] # k가 두 글자 이상이고 형태소 태그가 여럿인 경우 or 하나라도 명사가 아닌 경우 UM으로 등록 if len(k) > 1 and (len(m.pos(k)) > 1 or m.pos(k)[0][1][0:2] != 'NN'): out.append([eojeol[0:i], k, eojeol[i + j + 1:]]) return out