A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.geeksforgeeks.org/python/twitter-sentiment-analysis-webapp-using-flask/ below:

Twitter Sentiment Analysis WebApp using Flask

Twitter Sentiment Analysis WebApp using Flask

Last Updated : 23 Jul, 2025

This is a web app made using Python and Flask Framework. It has a registration system and a dashboard. Users can enter keywords to fetch live tweets from Twitter and analyze them for sentiment. The results are then visualized in a graph. The project uses the popular Tweepy API to connect to X (formerly twitter) in real time, retrieving tweet text and metadata for analysis.

Features of this Application Detailed Project Implementation Video: Tools and Technologies Used

This project requires installing xampp, install it from here. It comes with MySQL installation as well so you don't have to install it seperately.

Before creating the app, make sure to create a "user" databse in MySQL with 3 columns (name, email id and password).

Creating Flask App

To set up a basic flask app, refer to Create flask App.

Create app.py file, this will be our main flask app. In this file we establish a connection to our SQL database using the 'conn' object and also set a user cookie variable, which checks if the user has logged in, before redirecting him/her to the home page. This script also handles the user input on the login/register pages. 

Python
from flask import Flask, render_template, request, redirect, session
import mysql.connector
from sentiments import second
import os


app = Flask(__name__)

# initializing the user cookie
app.secret_key = os.urandom(24)

# blueprint to call the second python file in the project.
app.register_blueprint(second)

# establishing a connection with mysql database made in xampp
try:
	conn = mysql.connector.connect(
		host="localhost", user="root", password="enter your mysql password here", database="user_db")
	cursor = conn.cursor()
except:
	print("An exception occurred")

# call the login template when the url is http://localhost:5000/
@app.route('/')
def login():
	return render_template('login.html')

# call the register template when the url is http://localhost:5000/register
@app.route('/register')
def register():
	return render_template('register.html')


@app.route('/home')
def home():
	if 'user_id' in session:
		return render_template('home.html')
	else:
		return redirect('/')


@app.route('/login_validation', methods=['POST'])
def login_validation():
	email = request.form.get('email')
	password = request.form.get('password')

	cursor.execute(
		"""SELECT * from `users` WHERE `email` LIKE '{}' AND `password` LIKE '{}'""".format(email, password))
	users = cursor.fetchall()
	# check if a user has already logged in
	if len(users) > 0:
		session['user_id'] = users[0][0]
		return redirect('/home')
	else:
		return redirect('/login')


@app.route('/add_user', methods=['POST'])
def add_user():

# get user login data and pass the data to database
	name = request.form.get('uname')
	email = request.form.get('uemail')
	password = request.form.get('upassword')
	cursor.execute("""INSERT INTO `users` (`name`,`email`,`password`) VALUES ('{}','{}','{}')""".format(
		name, email, password))
	conn.commit()
	cursor.execute(
		"""SELECT * from `users` WHERE `email` LIKE '{}'""".format(email))
	myuser = cursor.fetchall()
	session['user_id'] = myuser[0][0]
	return redirect('/home')


@app.route('/logout')
def logout():
# close the session
	session.pop('user_id')
	return redirect('/')


if __name__ == "__main__":
	app.run(debug=True)

Code Breakdown:

sentiments.py

This file takes user input (a keyword and tweet count), fetches live tweets via the Tweepy API, cleans and analyzes them for sentiment (from -1 for negative to 1 for positive) and then creates a pie chart saved as an image for later display in HTML pages.

Python
from flask import Blueprint, render_template, request
import matplotlib.pyplot as plt
import os
import tweepy
import csv
import re
from textblob import TextBlob
import matplotlib
matplotlib.use('agg')

# Register this file as a blueprint
second = Blueprint("second", __name__, static_folder="static", template_folder="template")

# Render page when URL is called
@second.route("/sentiment_analyzer")
def sentiment_analyzer():
    return render_template("sentiment_analyzer.html")

# Class with main logic
class SentimentAnalysis:

    def __init__(self):
        self.tweets = []
        self.tweetText = []

    # This function connects to the Tweepy API and downloads tweet data
    def DownloadData(self, keyword, tweets):
        # Authenticating
        consumerKey = 'get your consumerkey from X (twitter) developer portal'
        consumerSecret = 'get your consumerSecret from X (twitter) developer portal'
        accessToken = 'get your accessToken from X (twitter) developer portal'
        accessTokenSecret = 'get your accessTokenSecret from X (twitter) developer portal'
        auth = tweepy.OAuthHandler(consumerKey, consumerSecret)
        auth.set_access_token(accessToken, accessTokenSecret)
        api = tweepy.API(auth, wait_on_rate_limit=True)

        # Convert tweets to integer
        tweets = int(tweets)

        # Searching for tweets (Updated to use api.search_tweets)
        self.tweets = tweepy.Cursor(
            api.search_tweets, q=keyword, lang="en").items(tweets)

        # Open/create a file to append data to
        csvFile = open('result.csv', 'a')

        # Use csv writer
        csvWriter = csv.writer(csvFile)

        # Creating variables to store sentiment info
        polarity = 0
        positive = 0
        wpositive = 0
        spositive = 0
        negative = 0
        wnegative = 0
        snegative = 0
        neutral = 0

        # Iterating through tweets fetched
        for tweet in self.tweets:
            # Append cleaned tweet text to list
            self.tweetText.append(self.cleanTweet(tweet.text).encode('utf-8'))
            analysis = TextBlob(tweet.text)
            polarity += analysis.sentiment.polarity

            # Categorize sentiment
            if analysis.sentiment.polarity == 0:
                neutral += 1
            elif 0 < analysis.sentiment.polarity <= 0.3:
                wpositive += 1
            elif 0.3 < analysis.sentiment.polarity <= 0.6:
                positive += 1
            elif 0.6 < analysis.sentiment.polarity <= 1:
                spositive += 1
            elif -0.3 < analysis.sentiment.polarity <= 0:
                wnegative += 1
            elif -0.6 < analysis.sentiment.polarity <= -0.3:
                negative += 1
            elif -1 < analysis.sentiment.polarity <= -0.6:
                snegative += 1

        # Write to csv and close file
        csvWriter.writerow(self.tweetText)
        csvFile.close()

        # Calculate percentages
        positive = self.percentage(positive, tweets)
        wpositive = self.percentage(wpositive, tweets)
        spositive = self.percentage(spositive, tweets)
        negative = self.percentage(negative, tweets)
        wnegative = self.percentage(wnegative, tweets)
        snegative = self.percentage(snegative, tweets)
        neutral = self.percentage(neutral, tweets)

        # Calculate average polarity
        polarity = polarity / tweets

        # Determine overall sentiment for HTML display
        if polarity == 0:
            htmlpolarity = "Neutral"
        elif 0 < polarity <= 0.3:
            htmlpolarity = "Weakly Positive"
        elif 0.3 < polarity <= 0.6:
            htmlpolarity = "Positive"
        elif 0.6 < polarity <= 1:
            htmlpolarity = "Strongly Positive"
        elif -0.3 < polarity <= 0:
            htmlpolarity = "Weakly Negative"
        elif -0.6 < polarity <= -0.3:
            htmlpolarity = "Negative"
        elif -1 < polarity <= -0.6:
            htmlpolarity = "Strongly Negative"

        # Generate pie chart
        self.plotPieChart(positive, wpositive, spositive, negative,
                        wnegative, snegative, neutral, keyword, tweets)
        print(polarity, htmlpolarity)
        return polarity, htmlpolarity, positive, wpositive, spositive, negative, wnegative, snegative, neutral, keyword, tweets

    def cleanTweet(self, tweet):
        # Remove links, special characters, etc. from tweet
        return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)", " ", tweet).split())

    # Function to calculate percentage
    def percentage(self, part, whole):
        temp = 100 * float(part) / float(whole)
        return format(temp, '.2f')

    # Function to plot and save pie chart
    def plotPieChart(self, positive, wpositive, spositive, negative, wnegative, snegative, neutral, keyword, tweets):
        fig = plt.figure()
        labels = ['Positive [' + str(positive) + '%]', 'Weakly Positive [' + str(wpositive) + '%]',
                'Strongly Positive [' + str(spositive) + '%]', 'Neutral [' + str(neutral) + '%]',
                'Negative [' + str(negative) + '%]', 'Weakly Negative [' + str(wnegative) + '%]',
                'Strongly Negative [' + str(snegative) + '%]']
        sizes = [positive, wpositive, spositive, neutral, negative, wnegative, snegative]
        colors = ['yellowgreen', 'lightgreen', 'darkgreen', 'gold', 'red', 'lightsalmon', 'darkred']
        patches, texts = plt.pie(sizes, colors=colors, startangle=90)
        plt.legend(patches, labels, loc="best")
        plt.axis('equal')
        plt.tight_layout()
        strFile = r"C:\Users\LENOVO\PycharmProjects\SentimentAnalysis\static\images\plot1.png"
        if os.path.isfile(strFile):
            os.remove(strFile)
        plt.savefig(strFile)
        plt.close()  # Close figure to free memory

@second.route('/sentiment_logic', methods=['POST', 'GET'])
def sentiment_logic():
    # Get user input from HTML form
    keyword = request.form.get('keyword')
    tweets = request.form.get('tweets')
    sa = SentimentAnalysis()
    
    # Set variables for Jinja template
    polarity, htmlpolarity, positive, wpositive, spositive, negative, wnegative, snegative, neutral, keyword1, tweet1 = sa.DownloadData(
        keyword, tweets)
    return render_template('sentiment_analyzer.html', polarity=polarity, htmlpolarity=htmlpolarity, positive=positive, 
                          wpositive=wpositive, spositive=spositive, negative=negative, wnegative=wnegative, 
                          snegative=snegative, neutral=neutral, keyword=keyword1, tweets=tweet1)

@second.route('/visualize')
def visualize():
    return render_template('PieChart.html')

Code Explanation:

Creating Templates

Templates in flask contains all the HTML files for the flask app. Let's look at the HTML files we need to create for this project one by one-

Login template:

HTML code for the page that displays the login form. The user enters a username and password, which has validations. Once the data is validated, these variables are passed to the main.py file, which connects to the SQL database to check if the login is valid.  

HTML
<!doctype html>
<html lang="en">
   <head>
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
      <!-- Bootstrap CSS -->
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
      <!-- Latest compiled and minified CSS -->
      <link rel="stylesheet" href=
         "https://maxcdn.bootstrapcdn.com/bootstrap/
         4.0.0/css/bootstrap.min.css">
      <!-- jQuery library -->
      <script src=
         "https://ajax.googleapis.com/ajax/libs/
         jquery/3.3.1/jquery.min.js"></script>
      <script src=
         "https://cdnjs.cloudflare.com/ajax/libs/
         popper.js/1.12.9/umd/popper.min.js"></script>
      <title>Login</title>
   </head>
   <!-- navigation bar design -->
   <body class="bg-nav">
      <nav class="navbar">
         <a href="" class="navbar-brand text-light">Sentiment Analysis</a>
      </nav>
      <!-- login form outer design -->
      <div class="container">
         <div class="row">
            <div class="col-md-8">
               <h1 class="text-light display-4 mt-100" style="font-size: 80px; font-weight: bold"> Welcome to this Twitter Sentiment Analysis! </h1>
            </div>
            <div class="col-md-4">
               <div class="card mt-100">
                  <div class="card-body">
                     <!-- login form logic -->
                     <form method="post" action="login_validation">
                        <div class="form_group">
                           <label> Email </label><br>
                           <input type="email" class="form-control" name="email"  id="email"> <br>
                           <small id="emailvalid" class="form-text
                              text-muted invalid-feedback">
                           Your email must be a valid email
                           </small>
                        </div>
                        <div class="form_group">
                           <label> Password </label><br>
                           <input type="password" class="form-control" name="password" id="password"><br>
                           <h5 id="passcheck" style="color: red;">
                              **Please Fill the password
                           </h5>
                        </div>
                        <input type="submit" class="btn btn-primary btn-block btn-lg" value="Login">
                     </form>
                     <br>
                     


<p> Not a member? <a href="/register"> Create Account</a></p>



                  </div>
               </div>
            </div>
         </div>
      </div>
      <script src="/static/app.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
   </body>
</html>
The Registration template:

HTML code for the page that displays the registration form. The user enters a username and password, which has validations. Additionally, the user's name becomes a value for the cookie that is set in the main.py file. 

Once the data is validated, these variables are passed to the main.py file, which connects to the SQL database to check if the login is valid.  

HTML
<!doctype html>
<html lang="en">
   <head>
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
      <!-- Bootstrap CSS -->
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
      <title>Registration</title>
   </head>
   <body class="bg-nav">
      <nav class="navbar">
         <a href="" class="navbar-brand text-light">Sentiment Analysis App</a>
      </nav>
      <div class="container">
         <div class="row">
            <div class="col-md-8">
               <h1 class="text-light display-4 mt-100" style="font-size: 80px; font-weight: bold"> Welcome to this Twitter Sentiment Analysis! </h1>
            </div>
            <div class="col-md-4">
               <div class="card mt-100">
                  <div class="card-body">
                     <form method="post" action="/add_user">
                        <label> Name </label><br>
                        <input type="text" class="form-control" name="uname"> <br>
                        <label> Email </label><br>
                        <input type="email" class="form-control" name="uemail"> <br>
                        <label> Password </label><br>
                        <input type="password" class="form-control" name="upassword"><br>
                        <input type="submit" class="btn btn-primary btn-block btn-lg" value="Login">
                     </form>
                     <br>
                     


<p> Already a member? <a href="/"> Login </a></p>



                  </div>
               </div>
            </div>
         </div>
      </div>
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
   </body>
</html>
 The HomePage Template:

HTML home page. The page has 2 main parts 

HTML
<!DOCTYPE html>
<html lang="en">
   <head>
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
      <!-- Bootstrap CSS -->
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
      <title>Home</title>
   </head>
   <body>
      <!-- code for the navigation header bar-->
      <header style="height: 80px" class="navbar navbar-dark sticky-top bg-nav flex-md-nowrap p-0 shadow">
         <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" style="font-size: 30px; font-weight: bold" href="#">
            {% if session['user_id'] %}
            <h3>Welcome {{session['user_id']}}</h3>
            {%endif%}
         </a>
         <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
         <span class="navbar-toggler-icon"></span>
         </button>
         <nav class="d-inline-flex mt-2 mt-md-0 ms-md-auto">
            <a class="me-3 py-2 text-decoration-none text-light" style="font-size: 20px" href="/sentiment_analyzer">Get started</a>
            <a class="me-3 py-2 text-light text-decoration-none" style="font-size: 20px" href="/home">Home</a>
            <a class="me-3 py-2 text-light text-decoration-none" style="font-size: 20px"  href="/visualize">Visualize</a>
            <a class="py-2 text-light text-decoration-none" style="font-size: 20px" href="https://www.tweepy.org/">Help</a>
         </nav>
         <ul class="navbar-nav px-3">
            <li class="nav-item text-nowrap">
               <a class="nav-link text-dark card" style="font-size: 20px; padding: 3px" href="/logout">Sign out</a>
            </li>
         </ul>
      </header>
      <style>
         .carousel-item {
         height: 34rem;
         background: black;
         color: white;
         position: relative;
         background-position: center;
         background-size: cover;
         }
         .carousel-caption{
         position: absolute;
         bottom: 0;
         left: 0;
         right: 0;
         padding-bottom: 10px;
         }
         .overlay-image{
         position: absolute;
         bottom: 0;
         left: 0;
         right: 0;
         padding-bottom: 0px;
         background-position: center;
         background-size: cover;
         opacity: 0.4;
         }
      </style>
      <!--This is the start of the image slider-->
      <div id="carouselExampleCaptions" class="carousel slide" data-bs-ride="carousel">
         <div class="carousel-indicators">
            <button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
            <button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="1" aria-label="Slide 2"></button>
            <button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="2" aria-label="Slide 3"></button>
         </div>
         <div class="carousel-inner">
            <div style="height: 100px">
               <div class="carousel-item active" >
                  <div class="overlay-image">
                     <img src="/static/images/slideone.jpg" style="width: 100%">
                  </div>
                  <div class="carousel-caption" >
                     <b>
                        <h1 style="font-size: 100px">Let's get started!</h1>
                     </b>
                     <br>
                     <a href="sentiment_analyzer" class="btn btn-primary btn-block btn-lg" style="background-color: crimson; font-size: 30px"> Click Here to Analyze Some Tweets</a>
                  </div>
               </div>
               <div class="carousel-item">
                  <div class="overlay-image">
                     <img src="/static/images/slidetwo.jpg" style="width: 100%">
                  </div>
                  <div class="carousel-caption" >
                     <b>
                        <h1 style="font-size: 100px"> How does this work? </h1>
                     </b>
                     <br>
                     <a href="https://www.tweepy.org/" class="btn btn-primary btn-block btn-lg" style="background-color: crimson; font-size: 20px"> Click Here to know more about this project</a>
                  </div>
               </div>
               <div class="carousel-item">
                  <div class="overlay-image">
                     <img src="/static/images/slidefour.jpg" style="width: 100%">
                  </div>
                  <div class="carousel-caption" style="align-self: start; padding-top: 20px " >
                     <b>
                        <h1 style="font-size: 100px"> WorkFlow</h1>
                     </b>
                     <br>
                     <div class="btn btn-primary btn-block btn-lg" style="background-color: #73AD21; color: black; font-weight: bold;
                        font-size:30px;text-align: left; font-family: 'Franklin Gothic Book'">
                        Enter a keyword of your choice <br>
                        Enter the no of tweets you want to search <br>
                        Voila! See instant Results! <br>
                        Click on Generate to View Detailed Data Visualization.
                     </div>
                  </div>
               </div>
            </div>
            <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="prev">
            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Previous</span>
            </button>
            <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="next">
            <span class="carousel-control-next-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Next</span>
            </button>
         </div>
      </div>
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"></script>
   </body>
</html>
sentiment_analyzer.py template

This template asks the users to enter a topic/word of their interest and the number of tweets based on that topic that users would like to analyze. 

Please note that Twitter has daily and hourly rate limits, which cannot be exceeded. 

This form passes the data to second.py file, which calculates the output and sets "jinja" variables. (Jinja allows passing values between python and HTML).These variables then display the output to users. 

HTML
<!DOCTYPE html>
<html lang="en">
   <head>
      <!-- Required meta tags -->
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
      <!-- Bootstrap CSS -->
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"></script>
      <title>Home</title>
   </head>
   <body class="bg-nav">
      <!-- code for the navigation header bar-->
      <header style="height: 80px" class="navbar navbar-dark sticky-top bg-nav flex-md-nowrap p-0 shadow">
         <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" style="font-size: 30px; font-weight: bold" href="#">Twitter Sentiment Analysis</a>
         <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
         <span class="navbar-toggler-icon"></span>
         </button>
         <nav class="d-inline-flex mt-2 mt-md-0 ms-md-auto">
            <a class="me-3 py-2 text-decoration-none text-light" style="font-size: 20px" href="/sentiment_analyzer">Get started</a>
            <a class="me-3 py-2 text-light text-decoration-none" style="font-size: 20px" href="/home">Home</a>
            <a class="me-3 py-2 text-light text-decoration-none" style="font-size: 20px"  href="/visualize">Visualize</a>
            <a class="py-2 text-light text-decoration-none" style="font-size: 20px" href="https://www.tweepy.org/">Help</a>
         </nav>
         <ul class="navbar-nav px-3">
            <li class="nav-item text-nowrap">
               <a class="nav-link text-dark card" style="font-size: 20px; padding: 3px" href="/logout">Sign out</a>
            </li>
         </ul>
      </header>
      <div class="container">
         <div class="row">
            <div class="card mt-100" style="margin-top: 50px">
               <div class="card-body">
                  <form method="post" action="sentiment_logic">
                     <label> Enter your search keyword </label><br>
                     <input type="text" class="form-control" name="keyword"> <br>
                     <label> Enter your number of tweets to analyze </label><br>
                     <input type="number" class="form-control" name="tweets"><br>
                     <input type="submit" class="btn btn-primary btn-block btn-lg" value="Search">
                  </form>
                  <br>
                  


<p> Need help? <a href="/register"> Click here </a></p>



               </div>
            </div>
         </div>
      </div>
      <!-- Optional JavaScript; choose one of the two! -->
      <!--output values-->
      <br>
      <br>
      <br>
      <h1 style="color: black">-----------------------------------------------------------------------------------</h1>
      <div style="text-align: center;">
         <div >
            {% if polarity %}
            <h3 style="color: white; text-align: center;font-size:30px; border-radius: 25px; background-color: black">How are people reacting on {{keyword}} by analyzing {{tweets}} Tweets</h3>
            {% endif %}
         </div>
      </div>
      <!--parent div for reports-->
      <div class="row">
         <div>
            <!--General sentiment report-->
            <div class="row">
               <div class="mt-100">
                  <h1 style="color: white; text-align: center;font-size:50px">General Report</h1>
                  <div class="alert alert-primary" role="alert" style="height:70px">
                     {% if polarity %}
                     <h1 style="text-align: center;font-size:30px"> The Average Sentiment is {{htmlpolarity}}  </h1>
                     {%endif%}
                  </div>
               </div>
            </div>
            <!--end of general report-->
            <!--start of polarity value-->
            <div class="row">
               <div class="mt-100">
                  <h1 style="color: white; text-align: center;font-size:50px">Sentiment Polarity</h1>
                  <div class="alert alert-primary" role="alert" style="height:70px">
                     {% if polarity %}
                     <h1 style="text-align: center;font-size:30px"> The sentiment polarity is {{polarity}} </h1>
                     {%endif%}
                  </div>
               </div>
            </div>
            <!--end of polarity value-->
         </div>
         <!-- end of parent div for reports-->
      </div>
      <div style="margin-top: 50px">
         <h1 style="color: white; text-align: center;font-size:50px">Detailed Report</h1>
         <div class="alert alert-primary" role="alert" style="height:400px">
            {% if polarity %}
            <h2 class="report-text"> {{spositive}} "% people thought it was strongly positive"</h2>
            <h2 class="report-text"> {{positive}} "% people thought it was positive"</h2>
            <h2 class="report-text"> {{wpositive}} "% people thought it was weakly positive"</h2>
            <h2 class="report-text"> {{neutral}} "% people thought it was neutral"</h2>
            <h2 class="report-text"> {{negative}} "% people thought it was negative"</h2>
            <h2 class="report-text"> {{wnegative}} "% people thought it was weakly negative"</h2>
            <h2 class="report-text"> {{snegative}} "% people thought it was strongly negative"</h2>
            {%endif%}
         </div>
      </div>
      <!--end of report-->
      <a href="visualize" class="btn btn-primary btn-block btn-lg" style="background-color: crimson; font-size: 30px"> Generate Visualization</a>
      <br>
      <br>
      <!-- Option 1: Bootstrap Bundle with Popper -->
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
      <!-- Option 2: Separate Popper and Bootstrap JS -->
      <!--
         <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js" integrity="sha384-SR1sx49pcuLnqZUnnPwx6FCym0wLsk5JZuNx2bPPENzswTNFaQU1RDvt3wT4gWFG" crossorigin="anonymous"></script>
         <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.min.js" integrity="sha384-j0CNLUeiqtyaRmlzUHCPZ+Gy5fQu0dQ6eZ/xAww941Ai1SxSY+0EQqNXNE6DZiVc" crossorigin="anonymous"></script>
         -->
   </body>
</html>
The PieChart Generation template: 

This HTML template simply displays an image file saved in our project. This image file is generated in the second.py file code. The image is a Pie Chart, which visually represents the results of sentiment analysis. The image is overwritten every time the code is run. 

HTML
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Data Visualization</title>
	<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
	<!-- Bootstrap CSS -->
	<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
</head>
<body>
	<header style="height: 80px" class="navbar navbar-dark sticky-top bg-nav flex-md-nowrap p-0 shadow">
		<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" style="font-size: 30px; font-weight: bold" href="#">Twitter Sentiment Analysis</a>
		<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
		<span class="navbar-toggler-icon"></span>
		</button>
		<nav class="d-inline-flex mt-2 mt-md-0 ms-md-auto">
			<a class="me-3 py-2 text-decoration-none text-light" style="font-size: 20px" href="/sentiment_analyzer">Get started</a>
			<a class="me-3 py-2 text-light text-decoration-none" style="font-size: 20px" href="/home">Home</a>
			<a class="me-3 py-2 text-light text-decoration-none" style="font-size: 20px" href="/visualize">Visualize</a>
			<a class="py-2 text-light text-decoration-none" style="font-size: 20px" href="https://www.tweepy.org/">Help</a>
		</nav>
		<ul class="navbar-nav px-3">
			<li class="nav-item text-nowrap">
			<a class="nav-link text-dark card" style="font-size: 20px; padding: 3px" href="/logout">Sign out</a>
			</li>
		</ul>
	</header>
	<div class="mt-100" style="padding-top: 100px; text-align: center">
		<img src="/static/images/plot1.png" >
	</div>
	<small style="color: red"> ** Last generated visual. Press CTRL+ Refresh to reload</small><br>
	<a href="sentiment_analyzer" class="btn btn-primary btn-block btn-lg" style="background-color: crimson; font-size: 30px"> Back </a>
	<br>
	<br>
</body>
</html>
Detailed project Implementation guidelines:
  1. Users can create an account with proper validations by clicking “Create Account.” Cookies help prevent URL rewriting.
  2. After logging in, they are redirected to the home page, which features a Bootstrap carousel slider.
  3. The logged-in user’s name is displayed using cookies, which also prevent unauthorized access to /home.
  4. The home page welcomes users by name and provides navigation options. Clicking “Get Started” leads to the main module.
  5. Users enter a keyword and the number of tweets to analyze, then click “Analyze” to fetch and process tweets via Tweepy.
  6. Results are displayed and users can generate a Pie Chart by clicking “Generate Visualization.”
  7. Clicking “How This Project Works” redirects users to Tweepy documentation.
  8. Users can log out anytime to end their session.
Use Case Diagram Running the Application

To run the flask application, use this command in terminal-

python app.py

And then uprn the development URL in a browser= "http://127.0.0.1:5000"

Note: Since March 2023, Twitter’s search endpoints require a paid plan (e.g., Basic tier, $100/month). The Free tier no longer supports searching tweets, so this app’s search feature won’t work without a subscription.



RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4