| |
| """ |
| 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() |