73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
import time
|
|
import requests
|
|
import xml.etree.ElementTree as ET
|
|
|
|
|
|
class NewsCollector:
|
|
"""동기 뉴스 수집 (Google News RSS)"""
|
|
@staticmethod
|
|
def get_market_news(query="주식 시장"):
|
|
url = f"https://news.google.com/rss/search?q={query}&hl=ko&gl=KR&ceid=KR:ko"
|
|
try:
|
|
resp = requests.get(url, timeout=5)
|
|
root = ET.fromstring(resp.content)
|
|
items = []
|
|
for item in root.findall(".//item")[:5]:
|
|
title = item.find("title").text
|
|
items.append({"title": title, "source": "Google News"})
|
|
return items
|
|
except Exception as e:
|
|
print(f"[News] Collection failed: {e}")
|
|
return []
|
|
|
|
|
|
class AsyncNewsCollector:
|
|
"""비동기 뉴스 수집 + 5분 캐싱"""
|
|
|
|
def __init__(self):
|
|
self._cache = None
|
|
self._cache_time = 0
|
|
self._cache_ttl = 300 # 5분
|
|
|
|
def get_market_news(self, query="주식 시장"):
|
|
"""동기 인터페이스 (하위 호환)"""
|
|
now = time.time()
|
|
if self._cache and (now - self._cache_time) < self._cache_ttl:
|
|
return self._cache
|
|
|
|
result = NewsCollector.get_market_news(query)
|
|
self._cache = result
|
|
self._cache_time = now
|
|
return result
|
|
|
|
async def get_market_news_async(self, query="주식 시장"):
|
|
"""비동기 뉴스 수집 (aiohttp + 캐싱)"""
|
|
now = time.time()
|
|
if self._cache and (now - self._cache_time) < self._cache_ttl:
|
|
return self._cache
|
|
|
|
try:
|
|
import aiohttp
|
|
url = f"https://news.google.com/rss/search?q={query}&hl=ko&gl=KR&ceid=KR:ko"
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(url, timeout=aiohttp.ClientTimeout(total=5)) as resp:
|
|
content = await resp.read()
|
|
root = ET.fromstring(content)
|
|
items = []
|
|
for item in root.findall(".//item")[:5]:
|
|
title = item.find("title").text
|
|
items.append({"title": title, "source": "Google News"})
|
|
|
|
self._cache = items
|
|
self._cache_time = now
|
|
return items
|
|
except ImportError:
|
|
# aiohttp 미설치 시 동기 fallback
|
|
return self.get_market_news(query)
|
|
except Exception as e:
|
|
print(f"[News Async] Collection failed: {e}")
|
|
# 캐시가 있으면 반환, 없으면 동기 fallback
|
|
if self._cache:
|
|
return self._cache
|
|
return self.get_market_news(query)
|