샘플 작업

[python, 샘플] 오늘의 운세 (신문사 RSS피드 활용)

woopii 2025. 4. 6. 00:03

개요

재미 삼아 만든 오늘의 운세.

조선일보 RSS 피드를 활용해 자동으로 운세 기사를 수집하고, 띠별로 정리된 내용을 JSON 형태로 저장하는 크롤러를 만듦.

이 스크립트는 Python을 기반으로 RSS, Selenium, BeautifulSoup 등 다양한 라이브러리를 조합하여 다음과 같은 역할을 수행.

  • 오늘 날짜 기준으로 ‘운세’ 관련 기사 자동 검색
  • 기사 내부에서 띠별 운세 정보만 추출
  • JSON 형식으로 변환 후 DB 저장

 

구현 방식

1. RSS 피드 필터링

  • 조선일보 RSS피트에서 오늘 날짜 및 "운세" 키워드를 포함한 기사만 필터링.
  • 날짜는 현재 날짜의 월/일을 기준으로 동적으로 생성.

 

RSS피드?

RSS (Really Simple Syndication) 피드는 웹사이트에서 제공하는 콘텐츠 요약 정보.
뉴스, 블로그, 포스트처럼 업데이트가 자주 되는 사이트에서 새 콘텐츠가 등록되면,
RSS 피드를 통해 제목, 링크, 요약 등을 받아올 수 있음.

예 : 조선일보 RSS 검색하면 다양한 실시간 정보를 볼 수 있는 RSS 피드를 확인할 수 있음

 

2. 기사 내용 크롤링 (Selenium + BeautifulSoup)

  • Selenium으로 기사를 열고, JavaScript 렌더링 완료 후 HTML을 가져옴.
  • BeautifulSoup으로 페이지를 파싱하고 "년생"이 포함된 문장만 추출.
  • "36년생" 같은 표현을 기준으로 태어난 해를 추출하고, 12간지 띠로 변환하여 정리.

 

3. JSON 변환 및 저장

  • 운세 데이터를 날짜, 제목, 링크, 띠별 내용 구조로 JSON 포맷으로 정리.
  • DB에 저장
    • Json을 MongoDB에 저장 (MongoDB Atlas)
    • 이부분은 샘플에 없음 

 

 

샘플 코드

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from datetime import datetime
import feedparser
import requests
from bs4 import BeautifulSoup
import json
import time
import re  # 정규식 모듈 추가
from db import save_contents

# 12간지 띠 매칭
zodiac_animals = {
    0: "원숭이", 1: "닭", 2: "개", 3: "돼지", 4: "쥐", 5: "소",
    6: "호랑이", 7: "토끼", 8: "용", 9: "뱀", 10: "말", 11: "양"
}

# RSS 피드 URL 설정
rss_url = "https://www.chosun.com/arc/outboundfeeds/rss/category/national/?outputType=xml"  # 예시: 구글 뉴스 RSS 피드

# 피드 가져오기
feed = feedparser.parse(rss_url)

# 원하는 키워드 목록 (예: AI 관련 뉴스만 가져오기)
formatted_date = datetime.today().strftime("%Y%m%d")
keywords = ["운세", f"{datetime.today().month}월", f"{datetime.today().day}일"]

# 피드 제목 출력
print(f"Feed Title: {feed.feed.title}")

# 필터링된 기사 목록
filtered_articles = [
    entry for entry in feed.entries
    if all(keyword.lower() in entry.title.lower() for keyword in keywords)  # AND 조건
]

# 결과 출력
print(f"필터링된 기사 {len(filtered_articles)}개 찾음.\n")

# Chrome 옵션 설정
options = Options()
options.add_argument("--headless")  # 브라우저 창 없이 실행
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1920x1080")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")

# ChromeDriver 실행
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=options)

# 전체 운세 데이터 저장
all_horoscopes = {}

for entry in filtered_articles:
    print(f"{entry.title}")
    print(f"{entry.link}")

    # 운세 페이지 URL 입력
    url = entry.link

    # 웹페이지 열기
    driver.get(url)

    # 페이지 로딩 대기
    time.sleep(3)  # 필요에 따라 조정

    # JavaScript 실행된 후 HTML 가져오기
    html = driver.page_source
    soup = BeautifulSoup(html, "html.parser")

    # 운세 내용 찾기
    horoscope_dict = {}

    for tag in ["p"]:
        elements = soup.find_all(tag)
        for elem in elements:
            text = elem.get_text(separator=" ").strip()

            # 불필요한 개행 및 공백 정리
            text = re.sub(r"\s+", " ", text)  # 여러 개의 공백을 하나로 변환

            # "년생"이 포함된 문장들만 필터링
            sentences = text.split(". ")
            for sentence in sentences:
                sentence = sentence.strip()
                if "년생" in sentence:
                    parts = sentence.split(" ")
                    year_str = parts[0].replace("년생", "")  # "36년생" -> "36"
                    content = " ".join(parts[1:])  # 운세 내용

                    # 연도 변환 후 띠 계산
                    if year_str.isdigit():
                        base_year = 1900
                        if int(year_str) <= int(str(datetime.today().year)[2:4]) :
                            base_year = 2000
                        
                        birth_year = int(year_str) + base_year
                        zodiac = zodiac_animals[birth_year % 12]

                        if zodiac not in horoscope_dict:
                            horoscope_dict[zodiac] = []
                        horoscope_dict[zodiac].append(f"{birth_year}년생 : {content}")

    # 데이터 저장
    all_horoscopes["date"] = formatted_date
    all_horoscopes["title"] = entry.title
    all_horoscopes["link"] = entry.link
    all_horoscopes["contents"] = horoscope_dict

# ChromeDriver 종료
driver.quit()

# # JSON 변환
# horoscope_json = json.dumps(all_horoscopes, indent=4, ensure_ascii=False)

# # 결과 출력
# print("\n 운세 데이터 (띠별 그룹화 완료):")
# print(horoscope_json)

save_contents(all_horoscopes)


# # 만약 태어난 년도가 있다면, 필링 처리
# request_birth_year = 1990
# result = {}
# horoscope_json_dict = json.loads(horoscope_json)

# for animal, messages in horoscope_json_dict["contents"].items():
#     for msg in messages:
#         if msg.startswith(f"{request_birth_year}년생"):
#             result = {
#                 "띠": animal,
#                 "운세": msg
#             }

# result_json = json.dumps(result, indent=4, ensure_ascii=False)
# print(result_json)

 

 

느낌점

데이터 찾기가 너무 힘듬, 

API로 제공되는곳은 과금이고, 신문사 웹 스크래핑 자체가 쉽지 않음.

쉬운 방식이 RSS이지만, 운세 데이터 자체가 거의 없음

 

결론 : 챗지피티로 하자
https://woopi1087.tistory.com/127

 

[python, 샘플] 오늘의 운세 (OpenAI 활용)

개요재미 삼아 만든 오늘의 운세. OpenAI를 활용해 띠별, 별자리별 운세데이터 생성. OpenAI통해서 오늘 날짜 기준으로 띠별, 별자리별 운세데이터 생성.JSON 형식으로 변환.DB 저장. 구현 방식1. 띠

woopi1087.tistory.com

 

'샘플 작업' 카테고리의 다른 글

[python, 샘플] 오늘의 운세 (OpenAI 활용)  (0) 2025.04.06