abdulrahman.id icon indicating copy to clipboard operation
abdulrahman.id copied to clipboard

Opiniometer

Open abdulrcs opened this issue 2 months ago • 0 comments


slug: opiniometer date: 04-Mar-2021 summary: Analyze an opinion on a specific topic based on Twitter posts! techStack: React, Python, Chart.js category: Personal Project githubLink: https://github.com/abdulrcs/Opiniometer image: https://github.com/abdulrcs/abdulrahman.id/assets/54136956/bbe7f444-095a-4683-b609-93684e119f99

Overview

Analyze whether an opinion on a specific topic is Positive / Negative / Neutral based on recent tweets! It's possible using the Natural Language Processing (NLP) concept called Sentiment Analysis that can determine if a chunk of text is positive, negative, or neutral based on its polarity.

Project Goals

I learned about Sentiment Analysis from my Linear Algebra professor at college and was inspired to combine those with my frontend engineering skills by creating a dynamic visualization with Chart.js.

Tech Stack

  • React: Used React for the front end with the use of React Hooks for state management and lifecycle, React Router that makes it possible to navigate between components and create a Single Web Application.
  • Framer Motion: A Motion system library that makes it smooth and fluid when transitioning between pages.
  • Chart.js A data visualization library for displaying the final result.
  • Python (Tweepy, TextBlob, Flask): Utilize Python for the Backend, which uses Tweepy to interact with the Twitter API, TextBlob to calculate the polarity of each text, and Flask as a RESTful API that serves all the results in a JSON to communicate in a Frontend.

Features ✨

  • Users can search any topic on Twitter
  • It will show a chart on how many tweets are positive/negative/neutral etc
  • The user can see the actual tweets!

Demo Video

After the API changes in Twitter, the live site no longer works, so here's a demo video I recorded back in 2021.

Design Process

I designed the site first before writing any code to decide on the colors, components, etc to make sure everything is consistent.

Pasted image 20240416064340

Then, I created each React component based on the Figma I made, and added a Tweet component, that I sliced based on the real Tweet component on Twitter, to handle the Check Tweets feature.

After that, I created the API endpoint with Python to analyze the tweets, while making sure to filter retweets and links because most of them are spam.

@app.route('/api/<string:s>', methods=['GET'])
def analysis(s):
  searchTerm = str(s)
  data = {}
  auth = tweepy.OAuthHandler(consumer_key=consumerKey, consumer_secret=consumerSecret)
  auth.set_access_token(accessToken, accessTokenSecret)
  api = tweepy.API(auth)
  quantity = 25
  tweets = tweepy.Cursor(api.search, q=searchTerm+" -filter:retweets -filter:links", lang="en",tweet_mode="extended").items(quantity)

  wpositive = 0
  positive = 0
  spositive = 0
  wnegative = 0
  negative = 0
  snegative = 0
  neutral = 0
  avgPolarity = 0
  data["tweets"] = []
  data["polarity"] = {}
  for tweet in tweets:
    analysis = TextBlob(tweet.full_text)
    polarity = analysis.sentiment.polarity
    avgPolarity += polarity
    if (polarity == 0):
      neutral+=1
      data["tweets"].append([str(tweet.full_text), "Neutral"])
    elif (polarity > 0 and polarity <= 0.3):
      wpositive+=1
      data["tweets"].append([str(tweet.full_text),"Weakly Positive"])
    elif (polarity > 0.3 and polarity <= 0.6):
      positive+=1
      data["tweets"].append([str(tweet.full_text), "Positive"])
    elif (polarity > 0.6 and polarity <= 1):
      spositive+=1
      data["tweets"].append([str(tweet.full_text),"Strongly Positive"])
    elif (polarity > -0.3 and polarity <= 0):
      wnegative+=1
      data["tweets"].append([str(tweet.full_text), "Weakly Negative"])
    elif (polarity > -0.6 and polarity <= -0.3):
      negative+=1
      data["tweets"].append([str(tweet.full_text), "Negative"])
    elif (polarity > -1 and polarity <= -0.6):
      snegative+=1
      data["tweets"].append([str(tweet.full_text), "Strongly Negative"])

  data["polarity"]["spositive"] = spositive
  data["polarity"]["positive"] = positive
  data["polarity"]["wpositive"] = wpositive
  data["polarity"]["snegative"] = snegative
  data["polarity"]["negative"] = negative
  data["polarity"]["wnegative"] = wnegative
  data["polarity"]["neutral"] = neutral

  return jsonify(data)

Learnings and Takeaway

Building Opiniometer was a lot of fun, it started from seeing a research project from my professor to making it live on a real site, this made me realize you can get an idea from anywhere, and implement it yourself while also adding your unique skill and personality into it!

abdulrcs avatar Apr 16 '24 00:04 abdulrcs