본문 바로가기

Python

Python 구글 트렌드 인기 검색 10위 카톡 나에게 보내기 (2)

728x90

테스트 메세지를 보내본다.

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

api 문서를보면 

메세지 타입이 여러가지 있는데 텍스트만 있어도 충분해서 텍스트를 사용한다.

텍스트 템플릿에 맞게 template-object를 정의한다.

https://developers.kakao.com/docs/latest/ko/message/message-template#text

object_type, text, link가 필수값이고 버튼을 선택적으로 달수있다.

 

테스트 메세지를 보내보자

template_object = {
    "object_type":"text", 
    "text" : "test", 
    "link" : {
        "web_url" : "https://developers.kakao.com", 
        "mobile_web_url" : "https://developers.kakao.com"
    }

};
headers = {'Content-Type' : 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer '+accessToken};
data = {"template_object" : json.dumps(template_object)};

res = requests.post('https://kapi.kakao.com/v2/api/talk/memo/default/send', headers=headers, data=data);
if res.status_code == 200 :
    print(res.text)
else :
    print(res.text)

json.dump로 json형태로 데이터를 보낸다.

테스트 메세지가 왔다. 자세히보기를 누르면 template_object에 정의한 link값으로 이동한다.

이제 feedparser로 데이터를 가져와서 메세지를 만들면 된다.

 

feed = feedparser.parse('https://trends.google.co.kr/trends/trendingsearches/daily/rss?geo=KR');
posts = feed['entries'];

print(posts)

rss링크를 feedparser.parse로 하면 데이터를 리턴하는데 entries에 원하는 정보가 담겨있다. 가져온 데이터를 posts에 담아 콘솔에 찍어보면 엄청 긴 데이터가 나오는데

가장 먼저나오는 삼성전자 데이터 형태처럼 되어있고 1위부터 나온다. 몇개가 담겨있는지 모르지만 난 10개만 뽑을예정이다.

필요한건 title, ht_news_item_title, ht_news_item_snippet, ht_news_item_url 4가지정도다.

published에 타임정보가 있는데 GMT로 담아오는것 같아 쓰진않는다.

 

값들을 이용해 template_object의 text값에 넣어줄 msgText를 만든다.

feed = feedparser.parse('https://trends.google.co.kr/trends/trendingsearches/daily/rss?geo=KR');
posts = feed['entries'];
   
msgText = "";
for i in range(10-1, -1, -1):
   # get date
   dateArr = posts[i]['published'].split(' ')
   temp_struct = time.strptime(dateArr[0] + " " + dateArr[1] + " " + dateArr[2] + " " + dateArr[3] + " " + dateArr[4], "%a, %d %b %Y %H:%M:%S")
   post_date = time.strftime("%Y-%m-%d %H:%M:%S", temp_struct)
   
   msgText += str(i+1) + ". " + posts[i]["title"] + "\n\n" \
   + html.unescape(posts[i]["ht_news_item_title"]) + "\n\n" \
   + html.unescape(posts[i]["ht_news_item_snippet"]) + "\n\n" \
   + posts[i]["ht_news_item_url"] + "\n";

   print(msgText)
   msgText = "";

10위부터 1위가 나와야하기때문에 9부터 역순으로 for문을 돌렸다.

날짜는 쓰지않지만 published의 값을 time을 이용해 커스텀 할 수 있어서 일단 적어뒀다.

핵심은 msgText에 파싱한 값들을 붙이는 부분이다.

 

1. 삼성전자

[갤럭시 언팩] 수세 몰린 삼성전자, 가격 낮춘 폴더블폰이 구원투수될까 ...

삼성전자가 '삼성 갤럭시 언팩 2021(이하 언팩)'을 통해 하반기 스마트폰 시장 공략에 돌입했다. 주요 모델은 폴더블 디스플레이가 적용된 갤럭시Z폴드3·플립3이다.

https://www.wikileaks-kr.org/news/articleView.html?idxno=112713

 

대략 이런 형태로 나올수 있게 msgText를 구성한다.

html.unescape를 쓰는 이유는 parsing된 데이터가 특수문자가 있는경우 escape문자로 나오는데 예를들면

 

체성분 측정하고, 다양한 앱 깔 수 있는 '갤럭시워치4' 나왔다
-> 체성분 측정하고, 다양한 앱 깔 수 있는 '갤럭시워치4' 나왔다

이런식으로 데이터가 파싱된다. 따라서 html.unescape를 사용해 escape문자를 unescape해준다.

 

이제 나에게 메세지 보내는 함수 msgToMe와 만료되어있을 access token을 갱신하는 updateAccessToken을 정의한다.

 

def updateAccessToken():
    data = "grant_type=refresh_token&client_id=" + restApiKey + "&refresh_token=" + refresh_token;
    header = {"Content-Type" : "application/x-www-form-urlencoded;charset=utf-8"}
    res = requests.post('https://kauth.kakao.com/oauth/token', headers=header, data=data)
    print(res.status_code)
    if res.status_code == 200 :
        global accessToken
        accessToken = res.json()["access_token"]
        print(accessToken)
        updateSql = "UPDATE Auth SET value = %s, moddate = now() WHERE name LIKE %s";
        cursor.execute(updateSql, (accessToken, "access_token"))
    else :
        errorSql = "INSERT INTO ErrorLog (status, error, error_description, error_code, regdate) VALUES (%s, %s, %s, %s, now())";
        cursor.execute(errorSql, (res.status_code, json.loads(res.text)["error"], json.loads(res.text)["error_description"], json.loads(res.text)["error_code"]))
        print(res.text)

토큰 갱신 api문서다.

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

 

global accessToken

- 파이썬에서는 전역에 선언한 accessToken에 값을 할당하기 위해서는 global으로 먼저 정의를 해줘야한다

 

accessToken = res.json()["access_token"]

- res.json()은 json으로 받은 response값을 딕셔너리 타입으로 변환시켜준다. 갱신된 acceess token을 전역변수에 할당

 

성공 시, DB에 토큰정보값을 update하고 에러시 로그를 insert하는 로직을 넣어줫다.

아직 미완성된 부분은 리프레쉬 토큰을 갱신하는 구문이 아직 없어서, 주기적으로 직접 갱신해서 db에 넣어줘야 하는데 나중에 추가할 예정이다.

access token update 후에  res.json()["refresh_token"] 값이 존재할 경우로 처리하면 될듯하다.

 

def msgToMe(msg, keyword):
    keyword = urllib.parse.quote(keyword);
    search_naver = "https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query="+keyword
    search_google = "https://google.com/search?q="+keyword
    template_object = {
        "object_type":"text", 
        "text" : msg, 
        "link" : {"web_url" : search_naver, "mobile_web_url" : search_naver}, 
        "buttons" : [
            {
                "title" : "네이버 검색", 
                "link" : {"web_url" : search_naver, "mobile_web_url" : search_naver}
            },
            {
                "title" : "구글 검색", 
                "link" : {"web_url" : search_google, "mobile_web_url" : search_google}
            }
        ]
    };
    headers = {'Content-Type' : 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer '+accessToken};
    data = {"template_object" : json.dumps(template_object)};
    res = requests.post('https://kapi.kakao.com/v2/api/talk/memo/default/send', headers=headers, data=data);
    if res.status_code == 200 :
        print(res.text)
    else :
        errorSql = "INSERT INTO ErrorLog (status, error, error_description, error_code, regdate) VALUES (%s, %s, %s, %s, now())";
        cursor.execute(errorSql, (res.status_code, 'msgToMe Error', json.loads(res.text)["msg"], json.loads(res.text)["code"]))
        print(res.text)
        print("accessToken :", accessToken);
        print("headers :", headers);

매개변수로 text값에 들어갈 msg와, keyword를 받고있다.

keyword는 구글 검색, 네이버 검색 버튼을 추가할것이기 때문에 검색 키워드로 사용할 매개변수값이다.

네이버 검색 url와 구글 검색 url은 직접 쳐보고 따오면 된다.

 

test로 보냇던 기존 형식과 크게 다르지않지만 추가적으로 button을 달아주었다. 최대 2개까지 가능하다.

마찬가지로 에러가 날경우 db에 로그를 insert하고있다.

 

이제 feedparser로 파싱되어 구성한 메세지를 msgToMe에 10번 보내면 된다. 보내기전 access token이 만료 되어 있을 수 있으니 updateAccessToken을 호출해주면된다.

 

def sendGoolTrend(num) :
    updateAccessToken()
    
    feed = feedparser.parse('https://trends.google.co.kr/trends/trendingsearches/daily/rss?geo=KR');
    posts = feed['entries'];
    
    msgText = "";
    for i in range(num-1, -1, -1):
        # get date
        dateArr = posts[i]['published'].split(' ')
        temp_struct = time.strptime(dateArr[0] + " " + dateArr[1] + " " + dateArr[2] + " " + dateArr[3] + " " + dateArr[4], "%a, %d %b %Y %H:%M:%S")
        post_date = time.strftime("%Y-%m-%d %H:%M:%S", temp_struct)
        
        msgText += str(i+1) + ". " + posts[i]["title"] + "\n\n" \
                + html.unescape(posts[i]["ht_news_item_title"]) + "\n\n" \
                + html.unescape(posts[i]["ht_news_item_snippet"]) + "\n\n" \
                + posts[i]["ht_news_item_url"] + "\n";
        msgToMe(msgText, posts[i]["title"])
        msgText = "";

sendGoolTrend(10);

 

매개변수로 인기 검색어 순위를 받는다.

10위까지 반복해서 msgToMe를 호출하는데 키워드로 파싱된 데이터의 title을 넘기고 있다.

잘 나온다. 별똥별 우주쇼를 한다고 하지만 안볼거다. 갤럭시 워치4 예약이 빡셌었다고 한다.

 

이제 로컬에서 개발은 완료, 서버에 올려서 데몬으로 돌리면 끝이다.

728x90