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 |
댓글