Skip to content

DailyMotion 경제/주식 동향 알리미 💵

Notifications You must be signed in to change notification settings

eldhdpswl/dailymotion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DailyMotion

1. DailyMotion 이란

Daily + Emotion 이라는 의미로 하루하루 경제, 주식 키워드에 관련된 뉴스의 sentiment 분석을 통해 하루하루의 경제의 Sentiment를 달력에 뉴스와 함께 보여준다. 경제/주식 관련 뉴스들의 전반적인 동향을 살피는데 도움을 주기 위해 만들어진 웹 서비스다.

Project Duration : 2021.10.24 ~ 2021.11.02

Server renewal Duration : 2021.11.10 ~ 2021.12.23

2. 구성

(1) Project Duration : 2021.10.24 ~ 2021.11.02

(2) Server renewal Duration : 2021.11.10 ~ 2021.12.23

3. 서버

  • Naver Cloud Flatform 에서 서버를 대여하여 사용
  • Micro server / ubuntu-18.04 / 2vCPU, 4GB Mem, 50GB Disk
  • MongoDB 를 사용하여 데이터 관리
  • Flask, Nginx, WSGI(uWSGI), Docker를 사용한 웹 서버

4. 데이터 수집 / 가공

  • Naver 에서 제공하는 API 를 사용하여 데이터를 수집하고 가공한다.
  • Scrapping 하여 데이터를 수집한다.
  • NaverCloudFunction 을 사용하여 서버의 DB 에 원격 접속하여 수집한 데이터를 저장한다.

1. 뉴스 수집

  • Naver News API 사용
  • [ title, originallink, link, description, pubDate ] 수집
 news_items = []

    for keyword in keywords:
        url = 'https://openapi.naver.com/v1/search/news.json'

        sort = 'date'
        start_num = 1

        params = {'display': display_num, 'start': start_num,
                  'query': keyword.encode('utf-8'), 'sort': sort}
        headers = {'X-Naver-Client-Id': client_id,
                   'X-Naver-Client-Secret': client_secret, }

        r = requests.get(url, headers=headers,  params=params)

        if r.status_code == requests.codes.ok:
            result_response = json.loads(r.content.decode('utf-8'))

            result = result_response['items']
            for item in result:
                originallink = item['originallink']
                link = item['link']

                if originallink == link:
                    item['naverNews'] = 'N'
                else:
                    item['naverNews'] = 'Y'

                item['imageUrl'] = scrape_image_url(link)

                if item['naverNews'] == 'Y':
                    content = scrape_content(link)
                    item['content'] = content if content != '' else item['description']
                else:
                    item['content'] = item['description']

소스코드 링크

2. 뉴스 본문 내용 수집

  • 수집한 URL 을 통해 뉴스의 본문을 수집한다.
  • Summary 를 하기 위한 본문 수집
    content = ''
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}

    try:
        data = requests.get(url, headers=headers)
    except SSLError as e:
        data = requests.get(url, headers=headers, verify=False)

    soup = BeautifulSoup(data.text, 'html.parser')
    content = ''

    if 'news.naver.com' in url:
        naver_content = soup.select_one(
            '#articeBody') or soup.select_one('#articleBodyContents')

        if not naver_content:
            return content

        for tag in naver_content(['div', 'span', 'p', 'br', 'script']):
            tag.decompose()
        content = naver_content.text.strip()

소스코드 링크

3. Summary

  • Clova Summary API 를 사용하여 뉴스 본문을 요약 한다.
  • Sentiment 분석 API 인 Clova Sentiment API 를 사용하기 위해서는 글자 수 제한이 1000자 이기 때문에 본문을 1000자 이하로 요약할 필요가 있다.
    collection.update_many({'date': {'$exists': False}}, [
        {'$set': {'date': {"$toDate": "$pubDate"}}}])

    target_date = cal_datetime_utc(before_date)

    summary_items = list(collection.find(
        {'summary': {'$exists': False}, 'date': {'$gte': target_date['date_st'], '$lte': target_date['date_end']}}, {'_id': False}))

    for item in summary_items:
        if 200 < len(item['content']) < 2000:
            result = summary(txt=item['content'], client_id=summary_api_info['client_id'],
                             client_secret=summary_api_info['client_secret']).replace('</b>', "").replace('<b>', "") or item['description'].replace('</b>', "").replace('<b>', "")
        else:
            result = item['description'].replace(
                '</b>', "").replace('<b>', "")
    headers = {'X-NCP-APIGW-API-KEY-ID': client_id,
               'X-NCP-APIGW-API-KEY': client_secret,
               'Content-Type': 'application/json'}

    document = {'content': txt}
    option = {'language': 'ko', 'model': 'news', 'tone': 0, 'summaryCount': 9}

    data = {'document': document, 'option': option}

    r = requests.post('https://naveropenapi.apigw.ntruss.com/text-summary/v1/summarize',
                      headers=headers, data=json.dumps(data))

    summary_txt = ''
    if r.status_code == requests.codes.ok:
        result_response = json.loads(r.content)
        summary_txt = result_response['summary']

소스코드 링크

4. Sentiment 분석

  • Clova sentiment api를 사용하여 summary한 내용으로 해당 기사의 sentiment를 분석한다.
    sentiment_items = list(collection.find(
        {'sentiment': {'$exists': False}, 'date': {'$gte': target_date['date_st'], '$lte': target_date['date_end']}}, {'_id': False}))

    for item in sentiment_items:
        if len(item['summary']) < 1000:
            result = sentiment(txt=item['summary'], client_id=sentiment_api_info['client_id'],
                               client_secret=sentiment_api_info['client_secret'])
        else:
            result = 'null'
    sentiment_items = []

    if r.status_code == requests.codes.ok:
        result_response = json.loads(r.content)

        j = {
            'sentiment': result_response['document']['sentiment'],
            'neutral': result_response['document']['confidence']['neutral'],
            'positive': result_response['document']['confidence']['positive'],
            'negative': result_response['document']['confidence']['negative'],
        }
        sentiment_items.append(j)

소스코드 링크

5. Daily Sentiment DB Collection 만들기

  • Flask Web App 에 하루하루의 경제/주식 동향을 올리기 위해서는 당일 뉴스들의 sentiment 를 모아서 그날의 최종 동향을 구하고 저장하는 Collection 을 만들고 업데이트 해야한다.
    target_date = cal_datetime(before_date)
    sentiment_items = list(collection.find(
        {'date': {'$gte': target_date['date_st'], '$lte': target_date['date_end']}}, {'_id': False}))

    neutral = 0
    positive = 0
    negative = 0

    for item in sentiment_items:
        try:
            sentiment = item['sentiment'][0]['sentiment']
            if (sentiment == 'neutral'):
                neutral += 1
            elif (sentiment == 'positive'):
                positive += 1
            elif (sentiment == 'negative'):
                negative += 1
        except IndexError: 
            print('IndexError 에러 발생, exception처리완료')

    sentiment = [neutral, positive, negative]
    max_sentiment = max(sentiment)

    if (neutral == max_sentiment and positive == max_sentiment and negative == max_sentiment):
        daily_sentiment = 'neutral'
    elif (neutral == max_sentiment and positive == max_sentiment):
        daily_sentiment = 'positive'
    elif (neutral == max_sentiment and negative == max_sentiment):
        daily_sentiment = 'negative'
    elif (positive == max_sentiment and negative == max_sentiment):
        daily_sentiment = 'neutral'
    elif (neutral == max_sentiment):
        daily_sentiment = 'neutral'
    elif (negative == max_sentiment):
        daily_sentiment = 'negative'
    elif (positive == max_sentiment):
        daily_sentiment = 'positive'

    sentiment = {
        'date': target_date['date_end'].strftime('%Y-%m-%d'),
        'neutral': neutral,
        'positive': positive,
        'negative': negative,
        'dailySentiment': daily_sentiment
    }
    collection_new.delete_one({'date': target_date['date_end'].strftime('%Y-%m-%d')})
    collection_new.insert_one(sentiment)

소스코드 링크

5. Roadmap

백엔드

  • 서버 만들기 - Naver Cloud
  • 경제 뉴스 수집하기 - Naver News API
    • Web Scrape
      • URL Image
      • 본문
    • DB에 저장하기 - MongoDB
    • Naver Cloud Function 만들기
  • 본문 요약하기 - Naver Summary API
    • DB에 저장하기 - MongoDB
    • Naver Cloud Function 만들기
  • Datetime 만들기 - Convert to UTC
  • Sentiment 분석하기 - Naver Sentiment API
    • DB에 저장하기 - MongoDB
    • Naver Cloud Function 만들기
  • 분석된 sentiment을 이용해서 당일 경제/주식 최종 동향 선별하기
    • 새로운 Collection으로 DB에 업데이트 하기 - MongoDB
    • Naver Cloud Function 만들기

Frontend

  • Flask Web App 만들기
    • DB에서 뉴스 데이터 가지고 오기
    • DB에서 sentiment 데이터 가지고 오기
    • Fullcalendar 사용해서 달력 구현하기
    • Implement Bootstrap v5.0
    • Design web page using HTML/CSS/Javascript

Release

  • Domain 사기
  • Github, FileZilla 사용해서 서버에 업로드 하기
  • 가상환경 구현하기

6. 데모

Home Calendar
News Contact

Home

Calendar

News

Contact

About

DailyMotion 경제/주식 동향 알리미 💵

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published