본문 바로가기
IT - 코딩/유용한 코드

블로그 자동화 with python, chat gpt api, selenium

by 조기정 2025. 1. 9.

 

나는 지금 네이버 경제뉴스를 자동화 하여 올리고 있습니다 => https://blog.naver.com/wzxcv123

인베스트에서 가장 인기있는 뉴스 top5를 가지고 요약해서 올립니다. 

정말 간단하게 open ai api 와, 네이버 블로그만 있으면 됩니다.

# open ai, 뉴스 크롤링 관련
import requests
from bs4 import BeautifulSoup
import openai
import time


# 포스팅 관련
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains, Keys
import pyperclip, time
from datetime import datetime


id = "네이버 ID"
passwd = "네이버 비번"
open_ai_key = "sk-OPEN AI 키"

# OPENAI API 키 설정

blog_site ='https://blog.naver.com/wzxcv123?Redirect=Write&'

위는 기본적 설정들이구요. 

 

 

 

 

 

 

 

# 뉴스 페이지 크롤링 함수
def crawl_investing_news():
    url = "https://www.investing.com/news/most-popular-news"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
    }
    response = requests.get(url, headers=headers)
    
    if response.status_code != 200:
        raise Exception("Failed to load page")
    
    soup = BeautifulSoup(response.text, "html.parser")
    articles_container = soup.find("div", attrs={"data-test": "news-container"})
    if not articles_container:
        raise Exception("Failed to find articles container")
    articles = articles_container.find_all("a", attrs={"data-test": "article-title-link"})[:5]
    
    news_list = []
    for article in articles:
        news_url = article["href"] if article["href"].startswith("http") else "https://www.investing.com" + article["href"]
        news_title = article.get_text(strip=True)
        news_list.append((news_title, news_url))
    
    return news_list

 

여기서는 가장 인기있는 뉴스 사이트 5개를 가져와서 GPT로 글으 요약하기 위한 뉴스 링크와 타이틀을 크롤링 하는 코드입니다. 

 

# 뉴스 본문 크롤링 함수
def crawl_news_content(url):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
    }
    response = requests.get(url, headers=headers)
    
    if response.status_code != 200:
        raise Exception("Failed to load news content")
    
    soup = BeautifulSoup(response.text, "html.parser")
    paragraphs = soup.find_all("p")
    if not paragraphs:
        raise Exception("Failed to find news content paragraphs")
    content = "\n".join([para.get_text(strip=True) for para in paragraphs])
    return content

 

각각의 뉴스 사이트를 들어가서 본문의 제목과 텍스트를 긁어오는 부분입니다.

 

# 뉴스 요약 함수
def summarize(text):
    # 아래 text는 뉴스 기사입니다 해당 기사를 요약하고 긍정적인지 부정적인지 판단해 주세요
    prompt = f"""
    
    Summarize the paragraph below and interpret whether it is a positive or negative sentiment.
    아래의 text는 뉴스 기사입니다. 대답은 한국어로 부탁해요.
    text:{text}
    """
    
    response = openai.ChatCompletion.create(
        model="gpt-4o", # "gpt-4", #gpt-4 ,gpt-4o-mini , gpt-4o, gpt-3.5-turbo
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3,
    )
    return response.choices[0].message.content

 

GPT가 요약하라고 프롬프트 넣는 부분입니다.

 

 

# 블로그에 포스팅 
def blog_posting(all_text):
    
    chrome_options = Options()
    chrome_options.add_argument("lang=ko_KR")
    chrome_options.add_argument('no-sandbox')
    chrome_options.add_argument('disable-gpu')
    chrome_options.add_argument("disable-dev-shm-usage")
    chrome_options.add_argument("--log-level=3")
    chrome_options.add_argument("--disable-3d-apis")
    driver = webdriver.Chrome(service=Service(), options=chrome_options)

    url = 'https://nid.naver.com/nidlogin.login?mode=form&url=https://blog.naver.com/wzxcv123'
    driver.get(url)
    # 로그인을 하면 블로그홈으로 자동으로 가게끔 url을 지정해준다 !

    bb = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "id"))
    )
    bb.click()
    # 네이버 로그인 창에서 ID=id인 항목이 나올때 까지 대기했다가, 찾으면 클릭

    a = pyperclip.paste()
    # 복붙을 이용해서 로그인할꺼라, 이미 클립보드에 있던 내용을 a에 복사 해놓자.

    pyperclip.copy(id)
    # id변수의 값을 클립보드로 옮김

    actions = ActionChains(driver)
    actions.key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL).perform()
    # 드라이버에서 컨트롤+V 효과를 냄 !

    time.sleep(1)
    # 봇인식 무서우니 1초정도 기다리기 ... !

    ## pw도 똑같음 !
    bb = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "pw"))
    )
    bb.click()
    pyperclip.copy(passwd)
    actions = ActionChains(driver)
    actions.key_down(Keys.CONTROL).send_keys('v').key_up(Keys.CONTROL).perform()


    #복붙 끝났으니 아까 a에 저장했던 값 다시 클립보드로 고고
    pyperclip.copy(a)

    # 로그인 버튼 기다렸다가, 버튼 누르기
    bb = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "log.login"))
    )
    bb.click()
    time.sleep(1)

    # 새로운 브라우저 로그인 자주 사용하는 기기 등록 요청시 취소함
    cc = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "new.dontsave"))
    )
    cc.click() # 클릭
    time.sleep(1)

    # 프레임으로 전환
    driver.switch_to.frame('mainFrame')

    # '글쓰기' 링크 클릭
    dd = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.LINK_TEXT, '글쓰기'))
    )
    dd.click()


    driver.get(blog_site)
    driver.switch_to.frame('mainFrame')


    # 제목과 본문에 사용할 텍스트 생성
    now = datetime.now()
    to_day = f"{now.year}년_{now.month}월_{now.day}일_{now.hour}시"
    title_text = "현재 인기 top5 경제뉴스 요약 " + to_day


    print(title_text)
    print(all_text)

    bb = WebDriverWait(driver, 3).until(
        EC.presence_of_element_located((By.XPATH, '//span[contains(text(),"제목")]'))
    )
    bb.click()
    actions = ActionChains(driver)
    actions.send_keys(title_text).perform()

    bb = WebDriverWait(driver, 3).until(
        EC.presence_of_element_located((By.XPATH, '//span[contains(text(),"본문에")]'))
    )
    bb.click()
    actions = ActionChains(driver)
    actions.send_keys(all_text).perform()

    time.sleep(1)

    # 첫 번째 "발행" 텍스트를 가진 span 요소 클릭
    publish_button_first = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "발행") and contains(@class, "text__d09H7")]'))
    )

    # 두 번째 "발행" 텍스트를 가진 span 요소 클릭
    publish_button_second = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '//span[contains(text(), "발행") and contains(@class, "text__sraQE")]'))
    )

    publish_button_first.click()
    time.sleep(1)
    publish_button_second.click()

 

이 부분이 사람마다 다를 수 있는데 크롬 기준 F12누르고

여기 왼쪽 부분을 클릭해서 어느 부분이니 html을 쪼개서 보시면 됩니다(모르겠으면 GPT한테 물어보기)

이런식으로 코드 작성하시면 자동 블로깅 가능!




# 메인 함수
def main():
    openai.api_key = open_ai_key
    news_list = crawl_investing_news()
    all_text = ""
    try:
        for title, url in news_list:
            print(f"크롤링 중: {title}")
            content = crawl_news_content(url)
            summary = summarize(content)
            print(f"요약 완료: {summary}")
            all_text += content + "\n\n"  # 각 뉴스 기사 본문을 줄바꿈과 함께 추가
        blog_posting(all_text)
        
            

    except Exception as e:
        print(f"오류 발생: {e}")
        
    

if __name__ == "__main__":
    

    
    
    main()

 

위 코드는 아까 정의한 함수들 전부 실행하는 코드입니다.

 

 

추가적으로

import schedule
import time
import subprocess

def run_script():
    # 스크립트 실행 경로 수정
    try:
        subprocess.run(['python', 'blog_posting_test copy.py'], check=True)  # 실제 스크립트 경로로 수정하세요.
    except Exception as e:
        print("오류 내역:",e)
        
    print("스크립트 실행 성공")

# 매일 아침 8시 50분에 실행
schedule.every().day.at("09:00").do(run_script)

# 매일 새벽 3시에 실행
schedule.every().day.at("03:00").do(run_script)

while True:
    schedule.run_pending()
    time.sleep(10)

 

이렇게 코드를 작성 할 수 있어요!  위 코드는 blog_posting_test copy.py를 실행시켜서  9시 ,3시에 블로깅을 자동 포스팅 하는거죠.