개요
재미 삼아 만든 오늘의 운세.
조선일보 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 |
---|