본문 바로가기

Python

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

728x90

네이버 실검이 없어진 지금 세상사를 모른다.

파이썬으로 구글 트렌드 인기 10위 긁어와서 카톡으로 뿌릴 예정이다.

이때 삼성전자 급락했음

 

일단 파이썬 설치는 라이브러리가 많은 아나콘다를 깔았다. IDE는 같이 설치된 스파이더를 사용해본다.

 

먼저 카톡으로 나에게 메시지를 보내려면 카카오 Developers에서 내 앱을 만들어야한다

카카오 개발자 > 내 애플리케이션 > 애플리케이션 추가

만들었으면 앱에 들어가서 요약정보를 보면 앱키 값들이 나와있다.

REST API를 사용할 예정이라 확인해둔다.

 

카카오 로그인탭에 들어가 활성화를 시켜주고 Redirect URL에 localhost와 개인 사이트가 있다면 추가해준다.

로그인후 리다이렉트될 url을 넣어야한다.

동의 항목은 모두 사용안함. 카카오 메시지 보내기만 선택동의로 해주었다.

카카오 로그인시에 동의 받는 목록이다. 처음 설정할땐 프로필 정보도 받았던거 같은데 자동 로그아웃처리가 되면서 토큰이 만료되는 이슈가 있어서 안함으로 수정했던것 같다.

 

허용 IP에 개발하는 로컬피시의 퍼블릭 아이피주소와 개발 완료한 파이썬을 데몬돌릴 서버의 아이피를 넣어준다.

본인 로컬 피씨의 퍼블릭 아이피는 네이버에 내 아이피만 쳐도 나온다.

 

설정이 완료되면 문서를 통해 api를 확인한다. 먼저 카카오 로그인으로 토큰을 받아야한다.

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

 

로그인 과정은 간단하게 말하면

1. 앱 설정에 등록된 앱키와 리다이렉트 주소로 인가코드를 받는다.

2. 앱키, 리다이렉트, 인가코드로 access token, refresh token을 받는다.

 

access token은 유효시간이 약 6시간, refresh는 2달로 알고있다.

 

한마디로 인가코드로 두개의 토큰을 받고 카톡 보낼때 access token을 사용하는데 짧은 유효기간이기 때문에 refresh token으로 새로 발급받으면서 이용하면 된다.

그리고 DB에 토큰정보를 저장해두고 select해서 사용할 예정이다. 이 과정을 파이썬으로 한다.

 

https://trends.google.co.kr/trends/trendingsearches/daily?geo=KR 

구글 트렌드의 대한민국 일별 인기 급상승 검색어 페이지다. 크롤링으로 가져올까 생각했지만

 

https://trends.google.co.kr/trends/trendingsearches/daily/rss?geo=KR  

rss를 제공하기때문에 python의 feedparser 라이브러리를 사용하기로 결정했다.

 

import requests
import json
import pymysql
import feedparser
import time
import html
import urllib

import할 목록이다. 아나콘다 설치할때 같이 깔린 프롬프트를 사용해 필요한 모듈을 설치해줘야한다.

anaconda3 디렉토리로 이동 후 

>pip install pymysql

식으로 설치하면된다. 필요한 모듈 pymysql과 feedparser를 설치해준다. 

이름으로 짐작이 되지만

pymysql - mysql 모듈

feedparser - rss의 데이터를 가져올 모듈

 

일단 전체 소스를 보면

db_connect = pymysql.connect(
    user = 아이디,
    passwd = 비밀번호,
    host = 호스트(아이피),
    db = 데이터베이스,
    autocommit = True,
    charset = 'utf8'
    )

cursor = db_connect.cursor(pymysql.cursors.DictCursor)

keySql = "SELECT * FROM Auth"

cursor.execute(keySql)
keyInfo = cursor.fetchall()

restApiKey = REST API 키
redirect_uri = 리다이렉트 URI

authCodeUrl = 'https://kauth.kakao.com/oauth/authorize?client_id='+restApiKey+'&redirect_uri='+redirect_uri+'&response_type=code';

authCode = 인가 코드

accessToken = 인가 코드로 받은 access token
refresh_token = 인가 코드로 받은 refresh token

for i in range(len(keyInfo)) :
    if keyInfo[i]["name"] == "refresh_token":
        refresh_token = keyInfo[i]["value"]
    if keyInfo[i]["name"] == "access_token":
        accessToken = keyInfo[i]["value"]
    if keyInfo[i]["name"] == "restapi_key":
        restApiKey = keyInfo[i]["value"]

# headers = {'Content-Type' : 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer '+accessToken};

def getAccessToken() :
    data = "grant_type=authorization_code&client_id=" + restApiKey + "&redirect_uri=" + redirect_uri + "&code=" + authCode; 
    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)
    print(res.text);

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);

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)

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";
                #+ post_date + "\n";
        msgToMe(msgText, posts[i]["title"])
        msgText = "";

sendGoolTrend(10);
#getAccessToken();

파이썬은 처음이라는 느낌이 코드에서 팍팍 느껴진다.

위에서 부터 보면,

authCodeUrl = 'https://kauth.kakao.com/oauth/authorize?client_id='+restApiKey+'&redirect_uri='+redirect_uri+'&response_type=code';

인가코드를 리턴하는 url이다. 파라미터로 rest api 키값과 리다이렉트 url을 주면 code값을 파라미터로 담아 리다이렉트되어 인가코드를 얻을 수 있다.

http://리다이렉트URL/?code=인가 코드값

이런 형태로 리다이렉트된다. code값을 선언한 authCode에 넣어준다.

authCode = 인가코드

이제 인가코드를 사용해 token을 받는다

토큰을 받는 rest api다 response로 access token과 refresh token 정보, 만료시간(초) 정보가 담겨있다. 

def getAccessToken() :
    data = "grant_type=authorization_code&client_id=" + restApiKey + "&redirect_uri=" + redirect_uri + "&code=" + authCode; 
    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)
    print(res.text);

db에 값을 insert하고 전역변수로 선언한 토큰 값들을 바꿔줘야하지만 일단 콘솔에 찍는다.

200으로 정상적으로 오면 토큰값들을 받을수 있다.

728x90