import streamlit as st import requests from transformers import pipeline import pandas as pd # Step 1: 네이버 뉴스 API 호출 함수 def fetch_naver_news(query, display=10, start=1, sort="date"): client_id = "I_8koTJh3R5l4wLurQbG" # 네이버 개발자 센터에서 발급받은 Client ID client_secret = "W5oWYlAgur" # 네이버 개발자 센터에서 발급받은 Client Secret url = "https://openapi.naver.com/v1/search/news.json" headers = { "X-Naver-Client-Id": client_id, "X-Naver-Client-Secret": client_secret, } params = { "query": query, "display": display, "start": start, "sort": sort, } response = requests.get(url, headers=headers, params=params) if response.status_code == 200: news_data = response.json() return news_data else: raise Exception(f"Error: {response.status_code}, {response.text}") # Step 2: Hugging Face 번역 모델 로드 (한국어 -> 영어) def load_translation_model(): translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en") return translator # Step 3: Hugging Face 정치 성향 분석 모델 로드 def load_huggingface_model(): classifier = pipeline("text-classification", model="bucketresearch/politicalBiasBERT") return classifier # Step 4: 정치 성향 분류 함수 def classify_political_sentiment(text, classifier): # 감성 분석 실행 result = classifier(text[:512]) # 입력이 너무 길면 잘라서 분석 sentiment = result[0] label = sentiment["label"] score = sentiment["score"] # 점수화 sentiment_score = score if label == "POSITIVE" else -score # 키워드 기반 분류 (진보/보수) progressive_keywords = ["복지", "평등", "민주", "환경", "사회적 책임"] conservative_keywords = ["안보", "전통", "경제", "성장", "질서", "국방"] if any(keyword in text for keyword in progressive_keywords): return "진보", sentiment_score elif any(keyword in text for keyword in conservative_keywords): return "보수", sentiment_score else: return "중립", sentiment_score # Step 5: 뉴스 분석 및 결과 출력 def analyze_news_political_orientation(news_items, classifier, translator): results = {"진보": 0, "보수": 0, "중립": 0} detailed_results = [] for item in news_items: title = item["title"] description = item["description"] combined_text = f"{title}. {description}" # 번역: 한국어 -> 영어 translated_text = translator(combined_text)[0]['translation_text'] # 정치 성향 분류 orientation, score = classify_political_sentiment(translated_text, classifier) results[orientation] += 1 detailed_results.append({ "제목": title, "요약": description, "성향": orientation, "점수": score, "링크": item["link"] }) return results, detailed_results # Streamlit 앱 시작 st.title("정치 성향 분석 대시보드") st.markdown("### 네이버 뉴스 데이터를 실시간으로 수집하고 정치 성향을 분석합니다.") # 검색 키워드 입력 query = st.text_input("검색 키워드를 입력하세요", value="정치") # 분석 시작 버튼 클릭 시 동작 if st.button("분석 시작"): with st.spinner("데이터를 분석 중입니다..."): try: # 네이버 뉴스 데이터 수집 news_data = fetch_naver_news(query, display=10) # 데이터 수집된 상태 확인 if not news_data or not news_data.get("items"): st.error("뉴스 데이터를 불러오는 데 실패했습니다.") return news_items = news_data["items"] # Hugging Face 모델 로드 classifier = load_huggingface_model() translator = load_translation_model() # 뉴스 데이터 분석 results, detailed_results = analyze_news_political_orientation(news_items, classifier, translator) # 분석 결과 시각화 st.subheader("분석 결과 요약") st.write(f"진보: {results['진보']}건") st.write(f"보수: {results['보수']}건") st.write(f"중립: {results['중립']}건") # 성향 분포 차트 st.subheader("성향 분포 차트") st.bar_chart(pd.DataFrame.from_dict(results, orient='index', columns=["건수"])) # 세부 결과 출력 st.subheader("세부 결과") df = pd.DataFrame(detailed_results) st.dataframe(df) # 링크 포함한 뉴스 출력 st.subheader("뉴스 링크") for index, row in df.iterrows(): st.write(f"- [{row['제목']}]({row['링크']}) (성향: {row['성향']}, 점수: {row['점수']:.2f})") except Exception as e: st.error(f"오류 발생: {e}")