▶ AI시대에서 개발자가 사는 법

3분 읽기

구글 트렌드와 ChatGPT로 자동 블로그 포스트 작성 및 배포하기


최근 몇 년간 인공지능과 자동화 기술의 발전으로 콘텐츠 생성과 관리가 훨씬 더 효율적으로 변하고 있습니다. 이번 포스트에서는 구글 트렌드를 활용하여 인기 검색어를 가져오고, 이를 ChatGPT를 이용해 블로그 포스트로 작성한 후, 고스트(Ghost) 플랫폼에 자동 배포하는 방법에 대해 알아보겠습니다.

저도 파이썬을 잘 몰라서 ChatGPT에게 물어가며 작업을 완료했습니다. 이런 것이 가능하다는것에 약간의 감동했습니다.

🔧 사전준비

파이썬이 깔려있어야 합니다. 저는 맥을 사용하므로 맥기준으로 설명드리겠습니다.

Homebrew 설치

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Python 설치

brew install python

VS Code 설치

개발 환경으로 VS Code를 사용합니다:

필요한 패키지 설치

pip install requests
pip install pytrends
pip install markdown-it-py
pip install openai==0.28
pip install pyjwt
pip install pillow

📊 구글 트렌드로 인기 검색어 가져오기

구글 트렌드는 특정 기간 동안의 인기 검색어를 제공하는 유용한 도구입니다. 이를 통해 현재 사람들이 무엇에 관심을 가지고 있는지 파악할 수 있습니다.

from pytrends.request import TrendReq

# pytrends 초기화 및 트렌드 검색
pytrends = TrendReq(hl='ko', tz=540)
kw_list = [""]
pytrends.build_payload(kw_list, geo='KR', timeframe='now 1-d')
trending_searches_df = pytrends.trending_searches(pn='south_korea')
top_keywords = trending_searches_df[0].tolist()

# 트렌드 목록 출력
print("오늘의 대한민국 트렌드 키워드:")
for i, keyword in enumerate(top_keywords, 1):
    print(f"{i}. {keyword}")

실행 방법

파일을 test1.py로 저장하고 터미널에서 실행:

python test1.py

실행 결과 예시

➜  python-app git:(main) ✗ python test1.py
오늘의 대한민국 트렌드 키워드:
1. 김해준
2. 비트코인
3. EWC
4. 아식스
5. 배우 강철
6. 해리스
...

🤖 ChatGPT로 블로그 포스트 작성하기

구글 트렌드에서 가져온 검색어를 바탕으로 ChatGPT를 이용해 블로그 포스트를 자동으로 작성할 수 있습니다.

import openai

keyword = "비트코인"

# OpenAI API 키 설정
openai.api_key = '<OPENAI에서 발급받은 API KEY>'

def generate_blog_content(keyword):
    prompt = f"""
    {keyword}에 대해 블로그 포스트를 작성해주세요.
    최신 정보를 포함하도록 작성해주시고, 사실이 맞는지 체크를 해주세요.
    단락마다 달리3에서 단락의 내용에 맞는 이미지를 삽입해주세요.
    아래 형식으로 태그 목록도 포함해주세요:
    ## 태그
    TAG1,TAG2,TAG3,TAG4
    """
    
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "You are a helpful assistant that writes blog posts. 한글로 써줘."},
            {"role": "user", "content": prompt}
        ],
        max_tokens=2048,
        temperature=0.7,
    )
    return response['choices'][0]['message']['content'].strip()

top_keyword_content = generate_blog_content(keyword)

if not top_keyword_content:
    print("블로그 콘텐츠 생성에 실패했습니다.")
    exit()

print(top_keyword_content)

실행 결과

  python-app python test2.py
# 비트코인: 디지털 시대의 혁신적인 자산
...

💡 참고: API로 사용하는 ChatGPT는 인터넷 검색을 못하는 것 같습니다. 실제 이미지 생성을 위해서는 DALL-E 3 API를 사용하거나 로컬에 Stable Diffusion을 설치하여 연동할 수 있습니다.

👻 고스트(Ghost) 플랫폼에 자동 배포하기

이제 작성된 블로그 포스트를 고스트 플랫폼에 자동으로 배포해봅시다. 전체 코드를 통합하면 다음과 같습니다:

전체 통합 코드

from pytrends.request import TrendReq
import openai
import requests
import json
import time
import pyjwt
import re
import io
import base64
from markdown_it import MarkdownIt
from PIL import Image

# 마크다운을 Ghost의 Lexical 형식으로 변환하는 함수
def markdown_to_lexical(markdown_content):
    md = MarkdownIt()
    tokens = md.parse(markdown_content)
    
    lexical_content = {
        "root": {
            "children": [],
            "type": "root",
            "version": 1
        }
    }
    
    current_node = lexical_content["root"]["children"]
    
    for token in tokens:
        if token.type == "heading_open":
            level = int(token.tag[1])
            current_node.append({
                "type": "heading",
                "tag": f"h{level}",
                "children": []
            })
            current_node = current_node[-1]["children"]
        elif token.type == "heading_close":
            current_node = lexical_content["root"]["children"]
        elif token.type == "paragraph_open":
            current_node.append({
                "type": "paragraph",
                "children": []
            })
            current_node = current_node[-1]["children"]
        elif token.type == "paragraph_close":
            current_node = lexical_content["root"]["children"]
        elif token.type == "inline":
            for child in token.children:
                if child.type == "text":
                    current_node.append({
                        "type": "text",
                        "text": child.content
                    })
    
    return lexical_content

# 태그 추출 함수
def extract_tags(markdown_content):
    tag_section = re.search(r'## 태그\n(.+)', markdown_content)
    if tag_section:
        tags_line = tag_section.group(1).strip()
        tags = tags_line.split(',')
        return [tag.strip() for tag in tags]
    return []

# 제목 추출 함수
def extract_title(markdown_content):
    match = re.search(r'^# (.+)', markdown_content, re.MULTILINE)
    if match:
        return match.group(1)
    return "Untitled"

# pytrends 초기화 및 트렌드 검색
pytrends = TrendReq(hl='ko', tz=540)
kw_list = [""]
pytrends.build_payload(kw_list, geo='KR', timeframe='now 1-d')
trending_searches_df = pytrends.trending_searches(pn='south_korea')
top_keywords = trending_searches_df[0].tolist()

# 트렌드 목록 출력
print("오늘의 대한민국 트렌드 키워드:")
for i, keyword in enumerate(top_keywords, 1):
    print(f"{i}. {keyword}")

# 사용자 입력을 통한 키워드 선택
user_input = input("원하는 키워드의 번호를 입력하세요 (또는 수동으로 입력하려면 엔터): ").strip()

if user_input:
    keyword_index = int(user_input) - 1
    keyword = top_keywords[keyword_index]
else:
    keyword = input("수동으로 키워드를 입력하세요: ").strip()

if not keyword:
    print("키워드가 없습니다. 프로그램을 종료합니다.")
    exit()

# OpenAI API 키 설정
openai.api_key = '<OpenAI에서 발급받은 API KEY>'

# ChatGPT로 블로그 콘텐츠 생성
def generate_blog_content(keyword):
    prompt = f"""
    {keyword}에 대해 블로그 포스트를 작성해주세요.
    최신 정보를 포함하도록 작성해주시고, 사실이 맞는지 체크를 해주세요.
    아래 형식으로 태그 목록도 포함해주세요:
    ## 태그
    TAG1,TAG2,TAG3,TAG4
    """
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": "You are a helpful assistant that writes blog posts. 한글로 써줘."},
            {"role": "user", "content": prompt}
        ],
        max_tokens=2048,
        temperature=0.7,
    )
    return response['choices'][0]['message']['content'].strip()

top_keyword_content = generate_blog_content(keyword)

if not top_keyword_content:
    print("블로그 콘텐츠 생성에 실패했습니다.")
    exit()

print(top_keyword_content)

# 마크다운을 Lexical 콘텐츠로 변환
lexical_content = markdown_to_lexical(top_keyword_content)

# 태그와 제목 추출
tags = extract_tags(top_keyword_content)
title = extract_title(top_keyword_content)
if not title:
    title = keyword

# Ghost Admin API 정보
ghostBlogDomain = "<고스트 블로그 도메인 주소>"
admin_api_url = f"{ghostBlogDomain}/ghost/api/admin/posts/"
admin_api_key = "<고스트 관리자에서 발급받은 admin api key>"

# JWT 생성
iat = int(time.time())
header = {'alg': 'HS256', 'typ': 'JWT', 'kid': admin_api_key.split(':')[0]}
payload = {
    'iat': iat,
    'exp': iat + 5 * 60,  # 토큰 유효 시간: 5분
    'aud': '/admin/'
}
secret = bytes.fromhex(admin_api_key.split(':')[1])
token = pyjwt.encode(payload, secret, algorithm='HS256', headers=header)

# 새로운 포스트 데이터
post_data = {
    "posts": [
        {
            "title": title,
            "slug": title,
            "status": "draft",  # draft 또는 published
            "visibility": "public",
            "lexical": json.dumps(lexical_content, ensure_ascii=False),
            "tags": tags
        }
    ]
}

# HTTP 요청 헤더
headers = {
    'Authorization': f'Ghost {token}',
    'Content-Type': 'application/json'
}

# 포스트 생성 요청
try:
    response = requests.post(admin_api_url, json=post_data, headers=headers)
    if response.status_code == 201:
        print("포스트가 성공적으로 생성되었습니다!")
    else:
        print(f"포스트 생성에 실패했습니다. 상태 코드: {response.status_code}")
        print(response.json())
except requests.exceptions.RequestException as e:
    print(f"Ghost API 호출 중 오류 발생: {e}")

🖼️ Stable Diffusion을 이용한 이미지 생성 (선택사항)

로컬에 Stable Diffusion WebUI를 설치했다면, 자동으로 헤더 이미지를 생성할 수 있습니다:

def generate_image(prompt):
    url = "http://127.0.0.1:7860/sdapi/v1/txt2img"
    payload = {
        "prompt": prompt,
        "negative_prompt": "(easynegative:1.2), (Bad Quality:1.5), watermark",
        "steps": 4,
        "cfg_scale": 2,
        "sampler": "DPM++ SDE",
        "seed": 1699193547,
        "size": [768, 1152]
    }
    response = requests.post(url, json=payload)
    if response.status_code == 200:
        image_data = response.json()["images"][0]
        image_bytes = base64.b64decode(image_data)
        return Image.open(io.BytesIO(image_bytes))
    else:
        print(f"이미지 생성 실패: {response.status_code}")
        return None

# 이미지 업로드 함수
def upload_image(image_path, token, ghostBlogDomain):
    headers = {
        'Authorization': f'Ghost {token}'
    }
    with open(image_path, 'rb') as img_file:
        files = {'file': (image_path, img_file, 'image/webp')}
        response = requests.post(
            f"{ghostBlogDomain}/ghost/api/admin/images/upload/",
            headers=headers,
            files=files
        )
        if response.status_code == 201:
            return response.json()['images'][0]['url']
        else:
            print(f"이미지 업로드 실패: {response.status_code}")
            return None

💡 참고: Stable Diffusion 실행 시 --api 옵션을 줘야 API를 사용할 수 있습니다.

📝 실행 결과

  python-app git:(main)  python3 AutoBlogPosting.py
오늘의 대한민국 트렌드 키워드:
1. 김해준
2. 비트코인
3. EWC
...
원하는 키워드의 번호를 입력하세요 (또는 수동으로 입력하려면 엔터):
수동으로 키워드를 입력하세요: 구글트렌드로 검색어를 가져와서 ChatGPT가 블로그 포스트를 작성하고 고스트에 자동배포

# 구글 트렌드와 ChatGPT로 자동 블로그 포스트 작성 및 배포하기
...
포스트가 성공적으로 생성되었습니다!

🎯 결론

위 과정을 통해 구글 트렌드에서 인기 검색어를 가져오고, ChatGPT를 이용해 블로그 포스트를 작성한 후, 고스트 플랫폼에 자동으로 배포하는 전 과정을 살펴보았습니다. 이 방법을 활용하면 최신 트렌드에 맞춘 콘텐츠를 효율적으로 생성하고 관리할 수 있습니다.

(헐 해당 포스팅도 위 코드를 활용했다는걸 들켜버렸네요 😅)

태그

구글트렌드, ChatGPT, 고스트, 자동화, API