| | |
| | """ |
| | CLI Demo for AI News Sentiment Analyzer |
| | Demonstrates the functionality via command line interface |
| | """ |
| |
|
| | import argparse |
| | import sys |
| | from datetime import datetime |
| | from api_handler import AINewsAnalyzer |
| |
|
| | def print_header(): |
| | """Print a nice header for the CLI""" |
| | print("π€ AI News Sentiment Analyzer") |
| | print("=" * 50) |
| | print() |
| |
|
| | def print_sentiment_emoji(sentiment): |
| | """Return emoji based on sentiment""" |
| | emoji_map = { |
| | 'positive': 'π', |
| | 'negative': 'π', |
| | 'neutral': 'π' |
| | } |
| | return emoji_map.get(sentiment, 'π€·') |
| |
|
| | def display_articles(df, max_articles=10): |
| | """Display articles in a formatted way""" |
| | if df.empty: |
| | print("β No articles found.") |
| | return |
| | |
| | print(f"π° Found {len(df)} articles") |
| | print("\nSentiment Distribution:") |
| | sentiment_counts = df['sentiment_label'].value_counts() |
| | for sentiment, count in sentiment_counts.items(): |
| | emoji = print_sentiment_emoji(sentiment) |
| | percentage = (count / len(df)) * 100 |
| | print(f" {emoji} {sentiment.title()}: {count} articles ({percentage:.1f}%)") |
| | |
| | print(f"\nπ Top {min(max_articles, len(df))} Articles:") |
| | print("-" * 80) |
| | |
| | for idx, (_, article) in enumerate(df.head(max_articles).iterrows(), 1): |
| | sentiment_emoji = print_sentiment_emoji(article['sentiment_label']) |
| | score = article['sentiment_polarity'] |
| | published = article['published_at'].strftime('%Y-%m-%d %H:%M') |
| | |
| | print(f"{idx:2}. {sentiment_emoji} [{article['source']}] {published}") |
| | print(f" {article['title']}") |
| | print(f" Sentiment: {article['sentiment_label'].title()} (Score: {score:.2f})") |
| | if article['description'] and len(article['description']) > 100: |
| | description = article['description'][:100] + "..." |
| | else: |
| | description = article['description'] or "No description available" |
| | print(f" π {description}") |
| | print(f" π {article['url']}") |
| | print() |
| |
|
| | def display_sentiment_analysis(df): |
| | """Display detailed sentiment analysis""" |
| | if df.empty: |
| | return |
| | |
| | print("\nπ Sentiment Analysis Summary:") |
| | print("-" * 40) |
| | |
| | |
| | avg_polarity = df['sentiment_polarity'].mean() |
| | avg_subjectivity = df['sentiment_subjectivity'].mean() |
| | |
| | print(f"Average Polarity: {avg_polarity:.3f} (Range: -1.0 to +1.0)") |
| | print(f"Average Subjectivity: {avg_subjectivity:.3f} (Range: 0.0 to 1.0)") |
| | |
| | if avg_polarity > 0.1: |
| | overall_mood = "π Generally Positive" |
| | elif avg_polarity < -0.1: |
| | overall_mood = "π Generally Negative" |
| | else: |
| | overall_mood = "β‘οΈ Generally Neutral" |
| | |
| | print(f"Overall Mood: {overall_mood}") |
| | |
| | |
| | if len(df[df['sentiment_label'] == 'positive']) > 0: |
| | most_positive = df.loc[df['sentiment_polarity'].idxmax()] |
| | print(f"\nπ Most Positive: \"{most_positive['title']}\" ({most_positive['sentiment_polarity']:.2f})") |
| | |
| | if len(df[df['sentiment_label'] == 'negative']) > 0: |
| | most_negative = df.loc[df['sentiment_polarity'].idxmin()] |
| | print(f"π Most Negative: \"{most_negative['title']}\" ({most_negative['sentiment_polarity']:.2f})") |
| |
|
| | def display_sources(df): |
| | """Display source breakdown""" |
| | if df.empty: |
| | return |
| | |
| | print("\nπΊ News Sources:") |
| | print("-" * 30) |
| | source_counts = df['source'].value_counts() |
| | for source, count in source_counts.head(10).items(): |
| | print(f" π° {source}: {count} articles") |
| |
|
| | def main(): |
| | parser = argparse.ArgumentParser(description='AI News Sentiment Analyzer CLI Demo') |
| | parser.add_argument('--query', '-q', |
| | default='artificial intelligence', |
| | help='Search query for news articles (default: "artificial intelligence")') |
| | parser.add_argument('--days', '-d', |
| | type=int, |
| | default=7, |
| | help='Number of days to look back (default: 7)') |
| | parser.add_argument('--sources', '-s', |
| | help='Comma-separated list of news sources (e.g., "techcrunch,wired")') |
| | parser.add_argument('--max-articles', '-m', |
| | type=int, |
| | default=10, |
| | help='Maximum number of articles to display (default: 10)') |
| | parser.add_argument('--sentiment-only', |
| | action='store_true', |
| | help='Show only sentiment analysis summary') |
| | parser.add_argument('--positive-only', |
| | action='store_true', |
| | help='Show only positive articles') |
| | parser.add_argument('--negative-only', |
| | action='store_true', |
| | help='Show only negative articles') |
| | |
| | args = parser.parse_args() |
| | |
| | print_header() |
| | |
| | try: |
| | |
| | analyzer = AINewsAnalyzer() |
| | |
| | print(f"π Searching for: \"{args.query}\"") |
| | print(f"π
Looking back: {args.days} days") |
| | if args.sources: |
| | print(f"π° Sources: {args.sources}") |
| | print() |
| | |
| | |
| | df = analyzer.get_ai_news_with_sentiment( |
| | query=args.query, |
| | days=args.days, |
| | sources=args.sources |
| | ) |
| | |
| | if df.empty: |
| | print("β No articles found. Try adjusting your search parameters.") |
| | return |
| | |
| | |
| | if args.positive_only: |
| | df = df[df['sentiment_label'] == 'positive'] |
| | print("π½ Filtered to show only POSITIVE articles") |
| | elif args.negative_only: |
| | df = df[df['sentiment_label'] == 'negative'] |
| | print("π½ Filtered to show only NEGATIVE articles") |
| | |
| | |
| | if args.sentiment_only: |
| | display_sentiment_analysis(df) |
| | else: |
| | display_articles(df, args.max_articles) |
| | display_sentiment_analysis(df) |
| | display_sources(df) |
| | |
| | print(f"\nβ
Analysis complete! Processed {len(df)} articles.") |
| | |
| | except KeyboardInterrupt: |
| | print("\nπ Analysis interrupted by user.") |
| | sys.exit(0) |
| | except Exception as e: |
| | print(f"β Error occurred: {e}") |
| | print("Please check your API key and internet connection.") |
| | sys.exit(1) |
| |
|
| | if __name__ == "__main__": |
| | main() |