TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 데이터 분석>

[파이썬] 자연어 처리(NLP) - 여자친구 선물 고르기 : 2(재도전 - 성공)

by 기록자_Recordian 2024. 5. 15.
728x90
반응형
시작에 앞서
해당 내용은 <파이썬으로 데이터 주무르기> -민형기 저, BJPUBLIC 출판사 의 내용을 토대로 작성되었습니다.
보다 자세한 내용은 해당 교재를 확인하여 주시기 바랍니다.

지난 챕터

 

 

[파이썬] 자연어 처리(NLP) - 여자친구 선물 고르기 : 1

시작에 앞서해당 내용은 -민형기 저, BJPUBLIC 출판사 의 내용을 토대로 작성되었습니다.보다 자세한 내용은 해당 교재를 확인하여 주시기 바랍니다.지난 챕터 [파이썬] 자연어 처리(NLP) 시작하기

puppy-foot-it.tistory.com

 

[파이썬] 자연어 처리(NLP) - 여자친구 선물 고르기 : 2(실패)

시작에 앞서해당 내용은 -민형기 저, BJPUBLIC 출판사 의 내용을 토대로 작성되었습니다.보다 자세한 내용은 해당 교재를 확인하여 주시기 바랍니다.지난 챕터 [파이썬] 자연어 처리(NLP) - 여자친

puppy-foot-it.tistory.com


지난 챕터 실패 요인 (feat. 워드클라우드)

 
지난 챕터에서는 네이버 지식인 크롤링을 성공하고, 빈도수가 높은 단어를 활용하여 워드클라우드를 그려보려고 하였으나.. 'ValueError: anchor not supported for multiline text' 라는 에러 메시지를 자꾸 받았다.
(이 에러는 워드클라우드의 텍스트가 여러 줄로 구성되어 있을 때 발생)


지식인 크롤링부터 재시작(feat. 10000개)

 
지난 챕터에서는 단어 1000개를 이용해서 단어 분석을 하였으나, 새롭게 하는 김에 10000개를 활용해서 진행하는 걸로 하겠다.

from tqdm import tqdm_notebook
import urllib.request
import time
import requests

# 검색할 질의어 설정
query = "여자 친구 선물"

# 검색 결과 페이지 URL
url = f"https://kin.naver.com/search/list.naver?query={query}"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

# 여자친구 선물에 대한 후보 텍스트를 저장할 리스트를 초기화.
present_candi_text = []  

start_num = 0  # 변수 초기화

# 범위 내에서 페이지를 반복하여 검색 결과를 가져오는 반복문.
for n in tqdm_notebook(range(1, 10000, 10)):
    # 현재 페이지 URL
    page_url = f"{url}&start={start_num}"
    
    # HTTP GET 요청 보내고 응답 받기
    response = requests.get(page_url)
    
    # BeautifulSoup을 사용하여 HTML을 파싱.
    soup = BeautifulSoup(response.text, "html.parser")
  
    # HTML에서 모든 <div> 태그를 찾아서 가져옴.
    tmp = soup.find_all('div')
    
    # 각 태그에서 텍스트를 추출하여 present_candi_text 리스트에 추가.
    for line in tmp:
        present_candi_text.append(line.text)
    
    # 서버에 부담을 주지 않기 위해 0.5초의 간격을 두고 잠시 대기.
    time.sleep(0.5)

지식인 단어 10000개 크롤링
한 번 껐다 켜서 그런지 잘 된다!

 
크롤링을 마치고,
okt 모듈을 import 하고
present_candi_text 리스트에서 처음 10,000개의 요소를 가져와서 하나의 문자열인 present_text에 추가
토큰화하는 과정까지 일사천리로 마치고 (전 챕터에서 했으니 상세한 설명 생략)

import nltk
from konlpy.tag import Okt; o = Okt()


# present_candi_text 리스트에서 처음 10000개의 요소를 가져와서 하나의 문자열인 present_text에 추가
#present_text 변수를 빈 문자열('')로 초기화
present_text = ''

# for 루프를 사용하여 present_candi_text의 각 요소를 순회
for each_line in present_candi_text[:10000]: # present_candi_text 리스트의 처음 10000개의 요소를 가져옴

# 각 요소를 present_text 문자열에 추가(줄바꿈 문자('\n')를 추가하여 한 줄씩 새로운 텍스트로 구분)    present_text = present_text + each_line + '\n'
tokens_ko = o.morphs(present_text)tokens_ko


tokens_ko = o.morphs(present_text)
tokens_ko

okt import 부터 토큰화까지

 
단어수를 세고, 빈도수가 높은 단어를 조회해보면

# 단어수 조회
ko = nltk.Text(tokens_ko, name='여자친구 선물')
print(len(ko.tokens))
print(len(set(ko.tokens)))

# 빈도수 조회
ko = nltk.Text(tokens_ko, name='여자친구 선물')
ko.vocab().most_common(100)

단어수 및 빈도수 조회

 
빈도수가 높은 단어 및 글자를 바탕으로 불용어 처리도 해주고

# 불용어처리(여러 번 수행)
stop_words = ['\n', '.', '>', '&', '...', ',', 'Q', 'A', '\n\n', '답변','대'
              '\n\n\n\n', '|', '\n\n\n', '수', '가', '을', '로', '에', '?',
              '를', '의', '(', ')', "'", '도', '다', '고', '는', '것', '이',
              '만', '한', '로', '들', '요', '입니다', '20', '30', '5', '(', ')',
              '!', '는', '좀', '중', '자살', '증권', '주식', '답변','\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t ',
             '\n\n\n\n\n\n\n', '지식', '좋을까요','궁금증','사람과','예방','복지',
             '1','iN', '은', '뭐','\n\n\n\n\n','질문','한국', '인','하기', '2024.01','해주세요','팝','R','B','1577-0199',
             '\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t','순','4', '7','8','6',
             '2','3','연관검색어','더','과','생명','인데','기간','최근','월','07','해주려고','2024.02','받고',
             '싶은데','안녕하세요','하려','합니다','브라우저','업데이트','있습니다','대한',
             '\n\n\n\n\n\n\n\n\n\n','지는','경제','정치','뭘','하는데','\n\n\n\n\n\n\n\n\n','"',
             '9.0','\n\n\n\n\n\n','\n\n\n\n\n\n\n\n\n\n\n\n','입력','\n\n\n\n','대', '못','주','달','지금',
             '문화','금융','음악','정확한','\n\n\n\n\n\n\n\n\n\n\n','권장','안내','오픈','희망','클릭','.!',
             '소중합니다','안','하세요','109','정신건강','HelpCall','이상','결과','1388','1588-9191','여러분','돕습니다',
             '의사','에게','여성가족부']

#용어가 제거된 텍스트를 기반으로 nltk 라이브러리의 Text 객체를 생성
tokens_ko = [each_word for each_word in tokens_ko if each_word not in stop_words]

ko = nltk.Text(tokens_ko, name='여자친구 선물')
ko.vocab().most_common(50)

불용어 처리
단어수가 늘다보니 불용어 수도 많아졌다

 
그리고 이를 토대로 빈도수 그래프도 그려본다.

plt.figure(figsize=(15,6))
ko.plot(50)
plt.show()

빈도수 그래프 그리기

 


워드 클라우드 그리기

 
워드 클라우드를 그리기 위한 모듈을 import 하고

from wordcloud import WordCloud, STOPWORDS
from PIL import Image
import platform
import matplotlib.pyplot as plt

#한글 폰트 문제 해결
path = "c:/Windows/Fonts/malgun.ttf"

from matplotlib import font_manager, rc
if platform.system() == 'Windows':
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Sorry')

%matplotlib inline

 
다중 텍스트를 다루기 위해 PIL(ImageDraw)의 multiline_text 함수를 사용하여 워드 클라우드 생성

from wordcloud import WordCloud
import matplotlib.pyplot as plt

# 데이터 준비
data = ko.vocab().most_common(300)

# 워드클라우드 객체 생성 (폰트 지정)
wordcloud = WordCloud(font_path="c:/Windows/Fonts/malgun.ttf",
                      relative_scaling=0.5,  # 상대적인 크기 조정값 설정
                      background_color='white',  # 배경은 흰색
                      width=800, height=400  # 이미지의 가로와 세로 크기 설정
                      )

# 텍스트 생성
text = "\n".join([f"{word}: {freq}" for word, freq in data])

# 워드클라우드 생성
wordcloud.generate(text)

# 이미지 출력
plt.figure(figsize=(16, 8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()

 

여자친구선물 빈도수 워드 클라우드
집념의 승리다!!


하트 그림에 워드 클라우드 그려보기

 
먼저 하단의 하트 그림을 다운받고

0.00MB

 
하트 그림으로 마스킹하고

#이미지 마스크 생성 (이미지 파일을 열어 Numpy 배열로 변환 후 mask 변수에 저장)
mask = np.array(Image.open('../data/09. heart.jpg')) #이미지 마스크 생성

# 워드클라우드의 색상을 지정하기 위해 이미지 색상 생성기 import
from wordcloud import ImageColorGenerator

# 마스크 이미지의 색상 정보를 가져와서 ImageColorGenerator 객체 생성
image_colors = ImageColorGenerator(mask)

 
하트 그림에 맞춰 워드 클라우드를 생성하는 코드를 입력하면

# 가장 빈번하게 등장하는 단어 200개를 추출
data = ko.vocab().most_common(200)

# 워드클라우드 객체 생성 (폰트 지정)
wordcloud = WordCloud(font_path="c:/Windows/Fonts/malgun.ttf",
                      relative_scaling=0.1, mask=mask, # 상대적인 크기 조정값 설정
                      background_color='white',  # 배경은 흰색
                      min_font_size=1,
                      max_font_size=100)  # 이미지의 가로와 세로 크기 설정

# 텍스트 생성
text = "\n".join([f"{word}: {freq}" for word, freq in data])

# 워드클라우드 생성
wordcloud.generate(text)

default_colors = wordcloud.to_array()

# 이미지 출력
plt.figure(figsize=(12, 12))
plt.imshow(wordcloud.recolor(color_func=image_colors), interpolation='bilinear')
plt.axis('off')
plt.show()

집념의 승리다!!!


 
 

728x90
반응형