본문 바로가기
Project/Blog New Post Noti

[New Post Noti] 새 포스팅 알림 트윗하기

by Haren 2021. 9. 8.

이 프로젝트 포스팅을 하면서 티스토리 플러그인에서 트위터로 내보내기 기능을 지원하는걸 알아버렸다...

하지만 뭔가 내 손으로 만들었다는게 중요하니까 회의감은 느끼지 않으려고 한다. 내가 만들었다는게 중요하다...

 

지난 포스팅에서는 트윗의 내용이 될 블로그를 파싱하는 과정을 다루어보았다.

 

>_지난 포스팅 보기

 

[New Post Noti] 블로그를 파싱해보자.

지난 포스팅에서는 Python의 패키지인 Tweepy를 활용해 Python으로 트윗을 작성해보았다. >_ 지난 포스팅 보기 [Blog New Post Noti] Python으로 트윗을 작성하기 지난 포스팅에서는 파이썬에서 트위터를 제

heibondk.tistory.com

 

오늘은 파싱해온 것을 바탕으로 트윗을 보내주는 기능을 어떻게 구현했는지 다루도록 하겠다.

 


>_twitter_bot.py 전체코드

import tweepy

f = open("./API_KEY/Twitter_Key", 'r')
tkn = f.readlines()

global link
link = "https://heibondk.tistory.com"

def twitting(notiTitle, notiDate, notiLink):
        apikey = str(tkn[0]).rstrip('\n') #컨슈머키
        apisecret = str(tkn[1]).rstrip('\n') #컨슈머 시크릿
        access_token = str(tkn[2]).rstrip('\n') #Access
        access_token_secret = str(tkn[3]).rstrip('\n') #Acceess 시크릿

        auth = tweepy.OAuthHandler(apikey, apisecret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth)
        api.update_status("STARGAZER 블로그에 다음과 같은 새 포스팅이 있습니다. \n " +
                                           "\n" + notiTitle + "\n" + "업로드일 : " + notiDate + "\n" + link + notiLink)

코드는 사실 지난 번에 자동 트윗 기능을 살펴보는 과정에서 크게 다를 바가 없다. 단지 twitter_bot.py에서 실행을 해주는게 아니라, main.py에 이 twitter_bot.py를 import 해서 twitting() 함수만 사용했다고 보면 된다.

 

>_ [New Post Noti] Python으로 트윗을 작성하기

 

[New Post Noti] Python으로 트윗을 작성하기

지난 포스팅에서는 파이썬에서 트위터를 제어하기 위한 패키지인 Tweepy에 대해서 알아보았다. 파이썬으로 트윗 봇을 만드려면 Tweepy 설치가 선행되어야 하므로, 아직 설치하지 않았다면 지난 포

heibondk.tistory.com

코드를 블럭별로 분석해가면서 어떻게 구현을 했는지 살펴보자.

 

import tweepy

당연히 Tweepy 패키지를 사용해야 하기 때문에, Tweepy 패키지를 import 해준다.

 

f = open("./API_KEY/Twitter_Key", 'r')
tkn = f.readlines()

내 트위터 앱의 API 키가 담긴 파일을 읽기 모드로 열어서 여러 줄로 읽어 배열의 형태로 tkn이라는 변수에 저장을 해주었다. .readlines()는 파일의 여러 줄의 텍스트를 줄 별로 배열로 저장해주는 역할을 한다. 파일 내에는 4줄로 컨슈머키, 컨슈머키 시크릿, 액세스토큰, 액세스토큰 시크릿이 순서대로 들어있기 때문에 배열로 가져와서 인덱스를 넣어주는게 좋을거라는 판단이 있었다.

 

키들을 별도의 파일에 넣어서 불러오는 이유는 이 프로젝트는 GitHub에 원격 리포지토리를 만들어서 관리를 하고 싶었고, 하드 코딩으로 토큰을 코드 내에 박아버리면 보안 상으로 문제가 된다. 내 트위터 앱의 키가 공개된다면 누구나 내 앱을 조작할 수 있기 때문이다. 따라서 키값이 담겨있는 파일과 새 포스팅과 기존 포스팅의 정보를 담고 있는 json 파일들도 .gitignore 파일로 만들어 원격 리포지토리에 연결이 되지 않도록 해줬다.

 

global link
link = "https://heibondk.tistory.com"

전역변수 link에는 내 블로그의 주소를 담아준다. 파싱을 하면서도 언급을 했었지만 티스토리 블로그의 포스팅 주소는 블로그 주소 + 포스팅 번호이기 때문에 트윗을 하는 과정에서 'link + 파싱한 포스팅 번호'를 인자로 넘겨주면 되기 때문이다.

 

>_twitting()함수

def twitting(notiTitle, notiDate, notiLink):
        api_key = str(tkn[0]).rstrip('\n') #컨슈머키
        api_key_secret = str(tkn[1]).rstrip('\n') #컨슈머 시크릿
        access_token = str(tkn[2]).rstrip('\n') #Access
        access_token_secret = str(tkn[3]).rstrip('\n') #Acceess 시크릿

        auth = tweepy.OAuthHandler(api_key, api_key_secret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth)
        api.update_status("STARGAZER 블로그에 다음과 같은 새 포스팅이 있습니다. \n " +
                                           "\n" + notiTitle + "\n" + "업로드일 : " + notiDate + "\n" + link + notiLink)

가장 메인이 되는 twitting() 함수이다. 매개변수로는 notiTitle, notiDate, notiLink가 들어간다. 해당 변수들은 트윗을 할 새 포스팅의 제목, 작성일, 포스팅 번호를 뜻한다.

 

api의 키와 접근 토큰들을 넘겨주는 과정은 위에서도 말했듯이 .readlines()로 키값들을 배열로 저장했기 때문에 tkn[n] 형식으로 인덱스를 넘겨주면 되었으며, 문자열로 변환하여 맨 뒤에 붙은 '\n' 이스케이프 문자를 .rstrip()을 사용해 제거해주었다. 이런 부분에 대해서 따로 나름대로의 정리를 해서 포스팅을 하고 싶어졌다....

 

인증 과정도 지난 번 자동 트윗 포스팅에서 다뤘으니 자세한 설명은 그쪽을 확인하면 될 것 같다.

 

지난 포스팅과 다른 점이 있다면 .update_status()를 사용하는 부분인데, 문자열 더하기를 이용해서 원하는 내용을 트윗하는 것을 알 수 있다. 

 

이제 main.py에서 트윗을 날려주는 부분을 보도록 하자.

 

>_main.py

import requests
from bs4 import BeautifulSoup
import json
from collections import OrderedDict
import myblogparser as exipsr
import twitter_bot as tb

myblog = requests.get("https://heibondk.tistory.com/")
soup = BeautifulSoup(myblog.content, "html.parser")
global link

def NewPost_file() : #새 포스팅을 검사하기 위한 함수
    file_data = OrderedDict()
    file_data["title"] = soup.select(".title")[0].get_text()
    file_data["date"] = soup.select(".date")[0].get_text()
    links = soup.select(".post-item")[0]
    href = links.find('a')
    href_last = href.attrs['href']
    file_data["href"] = href_last #새 포스팅의 포스트 번호를 가져오는 부분, 매우 지저분함;;
    with open('./POST_JSON/NewPost.json', 'w', encoding="utf-8") as make_file:
        json.dump(file_data, make_file, ensure_ascii=False, indent="\t")

def CompNewPost():
    with open('./POST_JSON/ExiNewPost.json', 'r') as orig_file, open('./POST_JSON/NewPost.json', 'r') as new_file:
        orig = json.load(orig_file)
        newf = json.load(new_file)

        if orig.get('href') != newf.get('href'):
            tb.twitting(newf.get('title'), newf.get('date'), newf.get('href'))
            print("달라요~")


NewPost_file()
CompNewPost()
exipsr.exiNewPost_file()

최상단에서 twitter_bot.pytb로 쓴다고 말하며 import 한 것을 확인할 수 있다.

 

>_CompNewPost()

def CompNewPost():
    with open('./POST_JSON/ExiNewPost.json', 'r') as orig_file, open('./POST_JSON/NewPost.json', 'r') as new_file:
        orig = json.load(orig_file)
        newf = json.load(new_file)

        if orig.get('href') != newf.get('href'):
            tb.twitting(newf.get('title'), newf.get('date'), newf.get('href'))
            print("달라요~")

ExiNewPost.jsonNewPost.json 두 파일을 열어 각각 orignewf라는 변수에 넣어주었다.

if 문으로 두 json 파일에서 "href" 안의 값, 즉 포스팅 번호를 비교하여 다르면 twitter_bot.py의 함수인 twitting()을 호출하며 매개변수를 인자로 전달하는 것을 볼 수 있다. 

print문 같은 경우는 트윗이 정상적으로 올라갈 조건인지를 확인하기 위해 넣은 테스트 코드다...

 

>_결과

따라서 새 포스팅을 올리고 main.py를 실행하면...

트윗이 잘 된다! 이렇게 모든 기능 구현이 완료되었다.

 


이렇게 오늘은 어떻게 새 포스팅 소식을 트윗했는지 알아보았다. 과정이 오래걸리거나 어려움이 많을 프로젝트라고 생각되었는데, intro에서 말했듯이 그리 어렵지는 않았고 걸린 시간도 짧았다. 기존의 telegram 챗봇 기능과의 병행도 엄두에 두었었는데 애초에 이 프로젝트는 트위터 봇을 만들고 싶어서 시작한 프로젝트였기에 챗봇 기능은 과감하게 삭제하였다. 텔레그램 챗봇의 인증이 강화된 것도 있고...

 

이제는 ssh 서버에 올려서 crontab을 사용해 실시간으로 트윗 봇이 작동하도록 하는 방법만 소개하면 이 프로젝트 포스팅 시리즈는 끝이 날 것 같다. 배포는 하고싶지만 내 블로그와 내 트위터에만 사용되는건데 굳이...? 싶어서 따로 배포는 하지 않을 생각이다. 다만, tweepy가 워낙 트위터 기능을 강력하게 지원하기에 다른 앱을 만들어서 배포할 생각은 있다.