ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 뉴스데이터를 이용한 문서유사도 확인
    Data Analysis 2021. 3. 5. 23:46
    반응형

    오늘 날짜부터 -n일차 까지 다음뉴스의 데이터를 긁어 오는 작업으로 시작합니다.

    날짜를 거꾸로 수집을 합니다.

    오늘로부터 며칠 전까지 이런식으로

    다음 랭킹뉴스에서 50개까지 url을 긁어온 뒤

    다시 for문을 이용해서 url을 접속해서 content를 긁어서 저장합니다.

    이 함수의 역할은 여기까지입니다.

    import requests
    from bs4 import BeautifulSoup
    import time
    import pandas as pd
    from datetime import datetime
    
    def daum(dates):
    
        # 다음뉴스 헤드라인 긁어오기
        files = pd.DataFrame()
        for date in dates:
            http=[]
            print(date,'', 'Daum 접속 중')
            httz = 'https://media.daum.net/ranking/popular/?regDate={}'.format(date)
            res = requests.get(httz)
            soup = BeautifulSoup(res.content, 'html.parser')
            body = soup.select('#mArticle > div.rank_news > ul.list_news2')
            body = body[0].find_all('a')
    
    
            for i in range(len(body)):
                t = body[i].get('href')
                http.append(t)
    
            # 중복제거
            http = list(set(http))
            
            for i in range(len(http)):
                res = requests.get(http[i])
                soup = BeautifulSoup(res.content, 'html.parser')
                body = soup.select('.article_view')[0]
    
                files = files.append(pd.DataFrame({
                    'date':date,
                    'title': soup.find('div', attrs={'class': 'head_view'}).h3.text,
                    'content': " ".join(p.get_text() for p in body.find_all('p')),
                    'link': http[i]
                }, index=[i]))
            time.sleep(15)
    
            # 텍스트파일에 댓글 저장하기
        files.to_csv('다음뉴스종합.csv',index=False,encoding='utf-8')
        print('파일 저장 완료!')
    
    # 현재로 부터 며칠 전까지 수집할 것인지 확인
    days = 1
    
    dates = [int(datetime.today().strftime('%Y%m%d')) - i for i in range(days)]
    daum(dates)

    데이터 수집 끝

     

    뉴스 content의 내용을 tfidf를 이용하여 유사도를 분석합니다.

    wikidocs.net/31698

     

    위키독스

    온라인 책을 제작 공유하는 플랫폼 서비스

    wikidocs.net

    tfidf를 모르시면 한번 확인하시길 바랍니다.

     

    이후 코드입니다.

    원래는 뉴스데이터 원본을 바로 Tf-idf를 이용하고, 바로 코사인유사도를 이용하여 분석하였습니다.

    하지만 조금 변경해서 명사추출로 먼저 데이터를 정제한 후에 모델에 입력합니다.

    그 이후에 Tf-idf -> 코사인유사도로 문서간의 유사도를 분석합니다.



    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.metrics.pairwise import linear_kernel
    from ckonlpy.tag import Twitter
    
    #dataframe에 null값이 있는 경우 공백을 넣어 null값 제거
    class TFIDF:
        def __init__(self,okky_data,word_dictionary):
            self.okky_data = okky_data
            self.word_dictionary = word_dictionary
            
            self.okky_data['noun_content'] = self.noun_extraction(self.okky_data['content'],
                                                             self.word_dictionary)
    
        # 전처리작업 (명사추출)
        def noun_extraction(self,text2,word_dictionary):
            t = Twitter()
            t.add_dictionary(word_dictionary, 'Noun')
    
            tokens = []
    
            for i in range(len(text2)):
                tokens_ko = ''
                noun = t.nouns(text2[i])
                for n in noun:
                    tokens_ko = tokens_ko + ' ' + n
                # 공백삭제
                tokens_ko = tokens_ko[1:]
                tokens.append(tokens_ko)
            return tokens
        
        # Null 제거 함수
        def avoid_null(self,data, header):
            data[header] = data[header].fillna('')
            return data[header]
    
        # Content의 tf-idf를 이용하여 유사도 확인
        def fit_tfidf(self):
            #content 데이터의 내용을 null 없이 가져옴
            self.okky_data['noun_content'] = self.avoid_null(self.okky_data, 'noun_content')
    
            #tf-idf계산 후 출력
            tfidfVectorizer = TfidfVectorizer()
            self.tfidf_metrix_of_tit = tfidfVectorizer.fit_transform(self.okky_data['noun_content'])
            return self.tfidf_metrix_of_tit
    
    
        #입력되는 train의 질문과 질문 데이터셋의 코사인유사도 값 중 상위 50개 질문목록을 가져오는 함수
        def top10_indices(self,data, q_num):
            #입력된 데이터의 코사인유사도 계산
            cos_sim = linear_kernel(data, data)
    
            cos_sim_score = list(enumerate(cos_sim[q_num])) 
            cos_sim_score = sorted(cos_sim_score, key = lambda x : x[1], reverse = True)
            #상위 10개 항목을 가져옴
            score = cos_sim_score[1:11]
            tag_indices = [i[0] for i in score]
    
            return tag_indices

    word_dictionary는 명사추출에 앞서서 원하는 명사를 추출하기 위해서 사전 역할을 합니다.

    위에서 긁어온 데이터를 다시 불러서 진행합니다.

    word_dictionary = ['전세집']
    
    okky_data = pd.read_csv(r'다음뉴스종합.csv', encoding = "utf-8", low_memory = False)

    데이터를 입력하면 명사 추출까지는 자동으로 입력하고

    그 이후 fit_tfidf 메서드를 불러서 유사도 metrix를 저장합니다.

    TFIDF = TFIDF(okky_data,word_dictionary)
    
    data_tit = TFIDF.fit_tfidf()

    마지막으로 코사인유사도로 순위가 나타난 문서들을 출력할 차례입니다.

    # 50개까지만 출력합니다.
    count = 50
    
    for i in range(len(okky_data[:count])):
        print(i, '/', len(okky_data))
        #질문 제목과 데이터셋의 유사도를 10위까지 가져옴
        tit_10_q = okky_data['content'].iloc[TFIDF.top10_indices(data_tit, i)]
        print(str(i),"번 뉴스와 유사한 내용을 가진 뉴스목록\n", tit_10_q) 

     

    정리

    1.데이터를 크롤링한다.

    2.명사만 따로 추출해서 저장한다.

    3.Tf-idf를 이용해서 문서유사도를 구한다.(핵심 단어만 찾아낸다.)

    4.구한 값을 이용해서 코사인유사도로 비슷한 문서를 찾는다.

    반응형
Designed by Tistory.