일전에 포스팅을 한번 했었기는 했는데, 그때도 의아했던 것이 '분명히 POST 방식을 쓰고 있는데 글 작성 컨텐츠를 모두 URL에 때려넣고 있는가?' 였었다. 심지어 공식 티스토리 API 문서도 그렇게 예시를 보여주고 있다.
https://tistory.github.io/document-tistory-apis/apis/v1/post/write.html
별다른 생각없이 '그래야 하나보다.' 라고 생각했는데, 이렇게 모든 정보를 URL에 때려넣게 되면 보안문제도 있거니와, 더 심각한 문제점이 하나 있는데, 포스팅하는 컨텐츠의 길이 제약을 심하게 받는다. 주식 종목분석기의 자동 포스팅을 하면서 테스트해본 결과 5*15정도의 테이블 하나를 컨텐츠로 넣으면 그 이상은 길이제한이 걸려 글 등록이 안된다.
한참을 지나서야 전송할 데이터들을 request body에 넣어서 api를 쏴볼 생각을 하게 되는데.... 해보니까 된다. -_-;; 이래서 게으르면 안된다. (사실 이 내용도 한참전에 알았는데 포스팅을 이제야 한다.) 새로 개선된 코드는 아래와 같다. config의 경우는 따로 치환해야한다. python에서 config 코드는 아래 링크를 참고하면 된다.
import requests
import re
import os
import markdown
from config.config import config
class PostingService:
access_token = None
def getAccessToken(self):
oauth_url = "https://www.tistory.com/oauth/authorize" # 인증 서버 접속용
login_url = 'https://www.tistory.com/auth/login' # 로그인 서버 접속용
callback_url = config["TISTORY"]["COLLBACK_URL"]
req_params = {
'client_id': config["TISTORY"]["CLIENT_ID"],
'redirect_uri': callback_url,
'response_type': 'token'}
login_info = {'loginId': config["TISTORY"]["LOGIN_ID"],
'password': config["TISTORY"]["PASSWORD"],
'redirectUri': callback_url}
with requests.session() as s:
response = s.post(login_url, data=login_info)
if (response.status_code == 200):
try:
redirect = s.get(oauth_url, params=req_params)
except requests.exceptions.ConnectionError as e: # 내겐 리다이렉트할 콜백 URL이 없는 주소를 적었기에 에러가 발생한다.
received = e.request.url
p = re.compile("(?<=access_token=)\w+")
m = p.search(received)
access_token = m.group()
self.access_token = access_token
def createPost(self, title, content, category_name, tag):
access_token = self.access_token
blog_name = config["TISTORY"]["BLOG_NAME"]
title = title # 제목 (필수)
content = content # 글내용(필수)
visibility = "0" # 발행상태 0비공개-기본, 1보호, 3발행
category_id = self.getCategoryId(category_name) # 카테고리 아이디 기본값 0
slogan = "" # 문자주소
tag = tag # 태그 ,로 구분
acceptComment = "1" # 댓글 허용 (0, 1 - 기본값)
password = "" # 보호글 비밀번호
url = 'https://www.tistory.com/apis/post/write'
data = { 'access_token':access_token,
'output':'json',
'blogName':blog_name,
'title':title,
'content':content,
'visibility':visibility,
'category':category_id,
'slogan':slogan,
'tag':tag,
'acceptComment':acceptComment,
'password':password
}
r = requests.post(url, data=data)
print(r.text)
return r.text
def getCategoryId(self, category_name):
access_token = self.access_token
blog_name = config["TISTORY"]["BLOG_NAME"]
url = f'https://www.tistory.com/apis/category/list?access_token={access_token}&output=json&blogName={blog_name}'
r = requests.get(url)
categories = r.json()['tistory']['item']['categories']
ret = None
for category in categories:
if category['name'] == category_name:
ret = category['id']
break
return ret
if __name__ == '__main__':
self.getAccessToken()
title = '타이틀'
content = '내용~ 긴내용도 이젠 괜찮아~~ '
category_name = '티스토리 카테고리 이름~~ '
tag = '태그,콤마로,구분됨'
self.createPost(title, content, category_name, tag)