데이터를 기반으로

특정 키워드 뉴스 카카오톡 자동 발송 구축하기 - (1) 본문

데이터 수집/API

특정 키워드 뉴스 카카오톡 자동 발송 구축하기 - (1)

이노후 2024. 3. 29. 00:02
728x90
반응형

여느 날과 같이 집에서 저녁을 먹다가 와이프가 갑자기 나에게 한가지를 물어보았다.

 

"자기야 특정 뉴스 매일 카톡으로 오면 좋겠는데 그런 기능은 없어?"

 

자존심으로 똘똘뭉친 나는 "아니? 그런게 왜 없어 당연히 있지 내가 만들어줄게!" 라고 호언 장담하였다.

 

그렇게... 해당 서비스는 제 와이프의 요청으로 인해서 구축하게 되었습니다.

(이상 배경 설명 끝)

 

 

먼저, 이전에 설명한 Naver News API 를 먼저 참고하고 오시면 좋을 것 같다.

https://ds92.tistory.com/139

 

네이버 뉴스 API 정리

특정 키워드 관련 뉴스들을 모니터링 하기 위해 네이버 api 로 뉴스를 가져오는 방법을 소개하고자 한다. https://developers.naver.com/main/ NAVER Developers 네이버 오픈 API들을 활용해 개발자들이 다양한

ds92.tistory.com

 

가장 먼저 개발하는 순서는 아래와 같았다.

 

1. Naver News API

    - 특정 키워드 뉴스

    - 중복 기사 검증

2. Kakao API ( 카카오톡 메시지 발송 )

3. 자동화

 

1번은 위 이전 게시물을 기반으로 가져와서 여러 키워드로 조회해 보았다.

 

 

위 사진과 같이 동일한 뉴스 내용의 기사들이 존재하는 것을 볼 수 있었다.

 

단순한 중복제거로는 제거가 되지 않을 것 같아서 텍스트 유사도 분석을 통해 유사도가 높은 것을 제거하는 로직을 추가하였다.

 

텍스트 유사도는 자카드 유사도 분석법을 사용하였다.

 

자카드 지수(Jaccard index) 란?

-> 두 집합 사이의 유사도를 측정하는 방법 중 하나이다. 자카드 계수(Jaccard coefficient) 또는 자카드 유사도(Jaccard similarity)라고도 한다. 자카드 지수는 0과 1 사이의 값을 가지며, 두 집합이 동일하면 1의 값을 가지고, 공통의 원소가 하나도 없으면 0의 값을 가진다. 자카드 지수는 아래의 식으로 정의된다.

 

위에서 가져온 뉴스 기사들을 토대로 자카드 지수를 각 기사별로 구해서 유사도가 0.3 이하인 것들만 추출했다.

# 자카드 유사도 함수 정의
def jaccard_similarity(s1, s2):
    s1, s2 = set(s1.split()), set(s2.split())
    return float(len(s1 & s2)) / len(s1 | s2)

# 유사도 계산 및 중복 제거
# 전처리
today_df['title2'] = today_df['title'].apply(lambda x : re.sub(r"[^\w\s\'\"]", "", x))
today_df2 = today_df.copy()

# threshold = 0.3  # 유사도 임계값 설정
for std_title in list(today_df['title2']) :
    today_df2['jaccard'] = today_df2['title2'].apply(lambda x : jaccard_similarity(std_title, x))
    today_df2 = today_df2.loc[(today_df2['jaccard'] <= 0.3) |
                              (today_df2['jaccard'] == 1) 
                             ].reset_index(drop=True)

 

이후 해당 today_df2라는 DataFrame을 기준으로 제목과 링크를 각각 하나의 텍스트로 취합해서 프린트를 해보았다.

 

 

제목을 보듯이 아주 조금 겹치는 부분이 존재하지만, 기존 것들보다 중복 내용 기사가 엄청 많이 줄어든 것을 확인할 수 있었다.

 

이제 보낼 콘텐츠(텍스트)는 완성이 되었다.

 

이후, 이제 카카오 톡으로 자동 발송을 해야하는 상황이다.

 

https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

이번 기회에 처음으로 OAuth2.0 를 살펴볼 수 있었다.

 

기존에 accese key 만 필요했던 API랑은 다르게 많은 인증이 필요했다.

 

간략하게 설명하면 access token을 발급받을 때 refresh token 도 같이 발급이 된다.

 

access token은 일정 기간이 지나면 유효하지 않은 값으로 변하기 때문에 일정 기간이 지나기 전에 refresh_token을 이용해서 해당 access token을 refresh 해줘야한다.

 

import requests
import json

refresh_token = '처음 얻은 refresh token'

headers={"Content-Type" : "application/x-www-form-urlencoded "}

url = 'https://kauth.kakao.com/oauth/token'
rest_api_key = '본인 키'
redirect_uri = '본인 uri'
client_secret = '본인 client secret key'

data = {
    'grant_type':'refresh_token',
    'client_id': rest_api_key,
    'refresh_token': refresh_token,
    'client_secret' : client_secret
    }

response = requests.post(url, headers=headers, data=data)
tokens = response.json()
# print(tokens)

access_token = tokens['access_token']

 

위 코드를 통해서 refresh_token 을 활용해서 access_token을 발급받아서 사용하는 구조로 보면 된다.

 

그렇게 refresh_token을 API를 통해 재등록(?)하고 나서 얻은 access_token을 활용하여 카카오톡 메시지를 전송하면 된다.

 

나에게 보내기 말고, 타인에게 보내기를 할 경우에는 특정 대상자의 여러 동의가 필요하다.

 

내 케이스는 그냥 나에게 보내고 전달해주는 식으로 베타 테스트를 진행했다.

 

# 텍스트 전송
url="https://kapi.kakao.com/v2/api/talk/memo/default/send"

headers={
    "Authorization" : "Bearer " + access_token
}


data={
    "template_object": json.dumps({
        "object_type":"text",
        "text":final_text,
        "link":{
            "web_url":"www.naver.com"
        }
    })
}

response = requests.post(url, headers=headers, data=data)

if response.json().get('result_code') == 0:
    print('메시지를 성공적으로 보냈습니다.')
else:
    print('메시지를 성공적으로 보내지 못했습니다. 오류메시지 : ' + str(response.json()))

 

 

위 코드에서 말하는 final_text 는 제목과 링크를 조합했던 하나의 발송 콘텐츠를 의미한다.

 

다음 게시글에서 해당 메시지를 자동으로 특정 시간에 발송되는 것을 설정하는 방법을 설명하고자 한다.

728x90
반응형

'데이터 수집 > API' 카테고리의 다른 글

네이버 뉴스 API 정리  (0) 2024.03.26
공공데이터 포털 약국 현황 API  (0) 2020.08.02
T-map API  (2) 2020.07.18