import streamlit as st import os import time from utils import fetch_news, analyze_sentiment, extract_topics, generate_tts import plotly.express as px import warnings warnings.filterwarnings("ignore", category=UserWarning) # Add custom CSS st.markdown(""" """, unsafe_allow_html=True) st.title("News Summarizer and Sentiment Analyzer") company_name = st.text_input("Enter a company name to get a sentiment report of its recent news.", placeholder="e.g., Google, Meta", value="") if st.button("Analyze"): with st.spinner("Fetching and analyzing news articles..."): time.sleep(1) articles_data = fetch_news(company_name) if not articles_data: st.error(f"No articles found for {company_name}. Check logs for details.") else: articles = [] sentiments = {"Positive": 0, "Negative": 0, "Neutral": 0} positive_articles = [] negative_articles = [] neutral_articles = [] for article in articles_data: summary = article["summary"].strip() or article["title"].split(" - ")[0].strip() source = article["title"].split(" - ")[-1].strip() if " - " in article["title"] else "" if source in summary: summary = summary.replace(source, "").strip() summary = f"{summary.rstrip(' -')} - {source}" sentiment = analyze_sentiment(summary) topics = extract_topics(summary) sentiments[sentiment] += 1 title = article["title"].split(" - ")[0].strip() if sentiment == "Positive": positive_articles.append(title) elif sentiment == "Negative": negative_articles.append(title) else: neutral_articles.append(title) articles.append({ "Title": article["title"], "Summary": summary, "Sentiment": sentiment, "Topics": topics, "Link": article["link"], "PubDate": article["pub_date"] }) import random detailed_comparisons = [f"- News {i + 1} {article['Sentiment'].lower()}ly discusses {', '.join(article['Topics'])}" for i, article in enumerate(articles)] dominant_sentiment = max(sentiments, key=sentiments.get) trends = f"{company_name} News Trends: {dominant_sentiment}" total_articles = sum(sentiments.values()) sentiment_count = f"{sentiments['Positive']} positive, {sentiments['Negative']} negative, {sentiments['Neutral']} neutral" intro_phrases = [ f"Spanning {total_articles} recent reports, the narrative surrounding {company_name} tilts {dominant_sentiment.lower()}, with {sentiment_count}.", f"Across {total_articles} articles in recent coverage, {company_name}’s story emerges as predominantly {dominant_sentiment.lower()}, reflecting {sentiment_count}.", f"Drawing from {total_articles} latest publications, {company_name}’s news landscape leans {dominant_sentiment.lower()}, underscored by {sentiment_count}." ] positive_phrases = [ f"With {len(positive_articles)} favorable accounts, {company_name} demonstrates notable progress, exemplified by '{random.choice(positive_articles) if positive_articles else 'no specific examples available'}'.", f"Boasting {len(positive_articles)} positive developments, {company_name} showcases strength, as evidenced in '{random.choice(positive_articles) if positive_articles else 'no notable instances'}'.", f"Highlighted by {len(positive_articles)} encouraging reports, {company_name} is forging ahead, with '{random.choice(positive_articles) if positive_articles else 'no standout reports'}' standing out." ] negative_phrases = [ f"However, {len(negative_articles)} troubling narratives raise concerns, including '{random.choice(negative_articles) if negative_articles else 'no specific concerns noted'}'.", f"Yet, {len(negative_articles)} adverse reports signal challenges, such as '{random.choice(negative_articles) if negative_articles else 'no highlighted issues'}'.", f"Nevertheless, {len(negative_articles)} concerning stories cast a shadow, notably '{random.choice(negative_articles) if negative_articles else 'no notable setbacks'}'." ] neutral_phrases = [ f"Additionally, {len(neutral_articles)} impartial updates provide context, such as '{random.choice(neutral_articles) if neutral_articles else 'no neutral updates available'}'.", f"Meanwhile, {len(neutral_articles)} balanced accounts offer insight, including '{random.choice(neutral_articles) if neutral_articles else 'no balanced reports'}'.", f"Furthermore, {len(neutral_articles)} objective pieces contribute details, like '{random.choice(neutral_articles) if neutral_articles else 'no objective details'}'." ] outlook_phrases_positive = [ f"In summary, {company_name} appears poised for a favorable trajectory.", f"All told, {company_name} stands on the cusp of a promising future.", f"Ultimately, {company_name} is positioned for an optimistic course ahead." ] outlook_phrases_negative = [ f"In conclusion, {company_name} confronts a challenging path forward.", f"Overall, {company_name} navigates a formidable road ahead.", f"To conclude, {company_name} faces a demanding horizon." ] outlook_phrases_mixed = [ f"In the final analysis, {company_name} balances opportunity and uncertainty.", f"On balance, {company_name} presents a complex outlook moving forward.", f"Ultimately, {company_name} reflects a blend of prospects and hurdles." ] final_text = random.choice(intro_phrases) + " " if positive_articles: final_text += random.choice(positive_phrases) + " " if negative_articles: final_text += random.choice(negative_phrases) + " " if neutral_articles: final_text += random.choice(neutral_phrases) + " " if sentiments["Positive"] > sentiments["Negative"]: final_text += random.choice(outlook_phrases_positive) elif sentiments["Negative"] > sentiments["Positive"]: final_text += random.choice(outlook_phrases_negative) else: final_text += random.choice(outlook_phrases_mixed) st.session_state.result = { "Company": company_name, "Articles": articles, "Comparative Sentiment Score": { "Sentiment Distribution": f"Positive: {sentiments['Positive']}, Negative: {sentiments['Negative']}, Neutral: {sentiments['Neutral']}", "Trends": trends, "Detailed Comparisons": "\n".join(detailed_comparisons) }, "Final Sentiment Analysis": final_text.strip() } if "result" in st.session_state: result = st.session_state.result if "error" in result: st.error(result["error"]) else: dist = result['Comparative Sentiment Score']['Sentiment Distribution'] sentiment_counts = { "Positive": int(dist.split("Positive: ")[1].split(",")[0]), "Negative": int(dist.split("Negative: ")[1].split(",")[0]), "Neutral": int(dist.split("Neutral: ")[1]) } fig = px.pie( values=list(sentiment_counts.values()), names=list(sentiment_counts.keys()), title="Sentiment Distribution", color_discrete_map={"Positive": "green", "Negative": "red", "Neutral": "gray"}, width=300, height=300 ) fig.update_layout(margin=dict(t=40, b=0, l=0, r=0)) st.sidebar.plotly_chart(fig, use_container_width=True) st.subheader(f"Analysis for {result['Company']}") for i, article in enumerate(result["Articles"], 1): st.write(f"**News {i}:** {article['PubDate']} [Read full article]({article['Link']})") st.write(f"Summary: {article['Summary']}") sentiment_class = f"sentiment-{article['Sentiment'].lower()}" st.markdown(f"Sentiment: {article['Sentiment']}", unsafe_allow_html=True) st.write("") st.subheader("Comparative Sentiment Analysis") st.write("Detailed Comparisons:") st.write(f"Sentiment Distribution: {result['Comparative Sentiment Score']['Sentiment Distribution']}") st.markdown(f"**{result['Comparative Sentiment Score']['Trends']}**", unsafe_allow_html=True) st.markdown(result["Comparative Sentiment Score"]["Detailed Comparisons"], unsafe_allow_html=True) st.subheader("Final Sentiment Analysis") st.write(result["Final Sentiment Analysis"]) language = st.selectbox("Select Audio Language", ["Hindi", "English"]) if st.button("Generate News Audio"): with st.spinner("Generating audio..."): audio_buffer = generate_tts(result["Final Sentiment Analysis"], 'hi' if language == "Hindi" else 'en') if audio_buffer: st.audio(audio_buffer, format="audio/mp3") else: st.error("Failed to generate audio. Check terminal logs.") st.markdown("""

Developed By: Krishna Prakash LinkedIn

""", unsafe_allow_html=True)