커서가 망쳐놓은 듯
This commit is contained in:
132
export_sniper.py
Normal file
132
export_sniper.py
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
관세청 수출 호재 감지 스나이퍼
|
||||
- 네이버 금융 속보에서 '수출/반도체' 관련 뉴스 실시간 감시
|
||||
- 호재 종목을 즉시 후보군에 추가
|
||||
"""
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import time
|
||||
import datetime
|
||||
import logging
|
||||
import re
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
logger = logging.getLogger("ExportSniper")
|
||||
|
||||
|
||||
class ExportSniper:
|
||||
"""관세청 수출 호재 감지기"""
|
||||
|
||||
def __init__(self):
|
||||
# 네이버 금융 실시간 속보 URL
|
||||
self.target_url = "https://finance.naver.com/news/news_list.naver?mode=LSS2D§ion_id=101§ion_id2=258"
|
||||
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
|
||||
self.keywords = ['관세청', '수출', '반도체', '잠정', '무역수지', '수출입']
|
||||
self.seen_news = set() # 이미 본 뉴스는 중복 출력 방지
|
||||
|
||||
# 종목명 매칭용 (반도체 관련)
|
||||
self.semiconductor_stocks = {
|
||||
'삼성전자': '005930',
|
||||
'SK하이닉스': '000660',
|
||||
'삼성SDI': '006400',
|
||||
'LG화학': '051910',
|
||||
'LG에너지솔루션': '373220',
|
||||
'포스코홀딩스': '005490',
|
||||
'포스코케미칼': '003670',
|
||||
}
|
||||
|
||||
def fetch_news(self) -> List[Dict]:
|
||||
"""네이버 금융 속보에서 뉴스 가져오기"""
|
||||
try:
|
||||
res = requests.get(self.target_url, headers=self.headers, timeout=5)
|
||||
soup = BeautifulSoup(res.text, 'html.parser')
|
||||
|
||||
# 뉴스 리스트 파싱
|
||||
news_items = soup.select('ul.realtimeNewsList li dl')
|
||||
|
||||
found_news = []
|
||||
|
||||
for item in news_items:
|
||||
title_tag = item.select_one('a')
|
||||
if not title_tag:
|
||||
continue
|
||||
|
||||
title = title_tag.text.strip()
|
||||
link = "https://finance.naver.com" + title_tag.get('href', '')
|
||||
|
||||
# 중복 체크
|
||||
if title in self.seen_news:
|
||||
continue
|
||||
|
||||
self.seen_news.add(title)
|
||||
|
||||
# 키워드 감지
|
||||
if any(keyword in title for keyword in self.keywords):
|
||||
# 긍정적 키워드 체크 (증가, 급증, 상승 등)
|
||||
positive_keywords = ['증가', '급증', '상승', '호조', '기록', '최대', '신고']
|
||||
is_positive = any(pk in title for pk in positive_keywords)
|
||||
|
||||
if is_positive:
|
||||
found_news.append({
|
||||
'title': title,
|
||||
'link': link,
|
||||
'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
})
|
||||
logger.info(f"🔥 [호재 포착] {title}")
|
||||
|
||||
return found_news
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 뉴스 크롤링 실패: {e}")
|
||||
return []
|
||||
|
||||
def extract_stocks_from_news(self, news_title: str) -> List[str]:
|
||||
"""
|
||||
뉴스 제목에서 관련 종목 코드 추출
|
||||
|
||||
:param news_title: 뉴스 제목
|
||||
:return: 종목 코드 리스트
|
||||
"""
|
||||
stocks = []
|
||||
|
||||
# 반도체 관련 종목 매칭
|
||||
for name, code in self.semiconductor_stocks.items():
|
||||
if name in news_title:
|
||||
stocks.append(code)
|
||||
|
||||
# "반도체" 키워드가 있으면 주요 반도체 종목 모두 추가
|
||||
if '반도체' in news_title:
|
||||
stocks.extend(['005930', '000660']) # 삼성전자, SK하이닉스
|
||||
|
||||
return list(set(stocks)) # 중복 제거
|
||||
|
||||
def get_hot_stocks(self) -> List[Dict]:
|
||||
"""
|
||||
호재 뉴스에서 관련 종목 추출
|
||||
|
||||
:return: [{'code': '005930', 'name': '삼성전자', 'reason': '뉴스 제목'}, ...]
|
||||
"""
|
||||
news_list = self.fetch_news()
|
||||
hot_stocks = []
|
||||
|
||||
for news in news_list:
|
||||
codes = self.extract_stocks_from_news(news['title'])
|
||||
for code in codes:
|
||||
# 종목명 찾기
|
||||
name = None
|
||||
for stock_name, stock_code in self.semiconductor_stocks.items():
|
||||
if stock_code == code:
|
||||
name = stock_name
|
||||
break
|
||||
|
||||
if name:
|
||||
hot_stocks.append({
|
||||
'code': code,
|
||||
'name': name,
|
||||
'reason': news['title'],
|
||||
'timestamp': news['timestamp']
|
||||
})
|
||||
|
||||
return hot_stocks
|
||||
Reference in New Issue
Block a user