본문 바로가기
NLP

뉴스 기사 분류

by 볼록티 2019. 11. 22.
728x90
반응형

크롤링을 하여 뉴스 기사를 수집하였다면 이제 그 뉴스를 카테고리별로 분류하는 작업을 해봅니다.

각 웹페이지에 등장하는 헤드라인 뉴스 기사 제목(url주소)을 카테고리별로 모두 수집합니다

 

 

 

 웹페이지의 뒷부분의 숫자를 기준으로 보통 페이지 수를 매기곤 합니다. 사이트마다 변형이 불규칙인 것도 있으니 규칙성을 잘 보셔야합니다. 규칙없이 이뤄진 경우에는 for문을 적용하기 힘들수도 있습니다.

 

카테고리 별 네이버 뉴스 웹페이지 주소 입니다. 네이버 뉴스는 다행히도 규칙적인 숫자로 웹페이지 주소가 할당되어 있었습니다.

import requests
from bs4 import BeautifulSoup

url="https://news.naver.com/main/main.nhn?mode=LSD&mid=shm&sid1="
category=[100,101,102,103,104] #정치, 경제, 사회, 생활/문화
news_url_list=[]

 

 

 

이 부분은 웹페이지에서 F12를 켜고 html을 자세히 보고, 각각에 포함된 개수가 몇개인지를 잘 파악한다면 쉽게 for문으로 해당 html에 모두 접근할 수 있습니다.

headline=[]

for i in category:
    home = url+str(i)
    soup = BeautifulSoup(requests.get(home).content, 'html.parser')
    x=len(soup.body.find_all("ul", class_="cluster_list")) # "ul"의 원소는 8개가 있음을 알 수 있습니다.
    ul= soup.body.find_all("ul", class_="cluster_list")
    for j in range(x):
        y=len(ul[j].find_all("li"))
        for k in range(y):
            headline.append((ul[j].find_all("li")[k].a["href"], i)) #(url, i)튜플 형태로 하여 후에 i를 label로 활용합니다.
            

위의 코드를 실행하면 그 페이지의 모든 헤드라인 기사의 링크를 가져오게 됩니다.

첫번째 for문은 카테고리별로 4번을 돌게 되고,

두번째 for문은 "ul" 집단의 개수만큼 돌게됩니다. 여기서는 8번입니다.

세번째 for문은 한 "ul" 이 포함한 "li" 개수만큼 돌게 됩니다.

 

 

이제 수집한 링크를 만큼 for문을 돌려서 각 링크 속 기사에 포함된 기사 내용을 수집하는 for문을 작성해봅니다.

 

contents=[]

for i in headline:
    soup = BeautifulSoup(requests.get(i[0]).content, 'html.parser')
    content=soup.body.find_all("div", class_="_article_body_contents")[0].text
    contents.append(content)

수집결과 contents리스트 속에 포함된 기사 개수는 124개라는 것을 알 수 있었고, 텍스트와 label 값이 잘 수집된 것으로 확인할 수 있었습니다.

 

 

추출한 뉴스기사에 대해 간단한 전처리를 해봅니다.

형태소 분석기는 과거 Twitter 였지만 바뀐 Okt 형태소 분석기를 사용하여 뉴스 기사에 명사를 추출하고 2글자 이상인 것만 추출합니다. 

from konlpy.tag import Okt
pos_tagger = Okt()

pos=[]
for content in contents:
    tmp = [i[0] for i in pos_tagger.pos(content) if ((i[1]=="Noun")and(len(i[0])>1))]
    pos.append(" ".join(tmp))  #이 형식으로 맞추어 주어야 후에 매트릭스 만들때 사용할 수 있습니다.

-> 각 뉴스 별로 contents가 명사만 남는 것을 확인할 수 있습니다.

 

 

 

이제 전처리한 뉴스기사를 토대로 if-idf 가중치를 준 BOW 행렬을 만들어 보도록 하겠습니다.

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(pos)

tf-idf는 기본적인 단어 출현 방식의 BOW행렬에 가중치를 줌으로써 단어들 간의 중요도를 측정할 수 있게 도와주는 행렬입니다. feature 값이 여전히 크다는 것이 단점입니다. 문서에서 뽑은 모든 단어를 feature로 사용하기 때문입니다.

 

a=[]
len(set([a.extend(i.split()) for i in pos]))

-> tfidf matrix의 feature의 수를 알 수 있다.

 

vectorizer.get_feature_names()

-> matrix의 feature들을 볼 수 있다.

 

 

 

tf-idf 행렬을 이용하여 KMeans로 클러스터링을 해보록한다.

 

 

from sklearn.cluster import KMeans

kmeans= KMeans(n_clusters=4, n_init=50, verbose=1)
kmeans.fit(tfidf_matrix)

print(kmeans.labels_)
print([str(j)[-1] for i,j in contents])

-> kmeans 클러스터링을 통해 유사한 집단끼리 분류가 되었고, 이를 기존의 라벨값과 비교 하면서 유사한 정도를 파악해 볼 수 있다..

728x90
반응형

'NLP' 카테고리의 다른 글

IMDB 영화 댓글 크롤링 코드  (2) 2019.11.28
코사인 유사도를 활용한 유사 문서 검색  (0) 2019.11.22
크롤링 4  (0) 2019.11.21
크롤링 3  (0) 2019.11.21
크롤링 2  (0) 2019.11.21

댓글