📜  使用PythonTwitter 情绪分析

📅  最后修改于: 2021-10-20 12:20:30             🧑  作者: Mango

本文通过使用Python解析从 Twitter 获取的推文来介绍任何主题的情绪分析。

什么是情感分析?
情感分析是“计算”确定一篇文章是正面、负面还是中性的过程。它也被称为意见挖掘,可以得出演讲者的意见或态度。

为什么要进行情感分析?

  • 业务:在营销领域,公司使用它来制定战略,了解客户对产品或品牌的感受,人们对他们的活动或产品发布的反应,以及消费者不购买的原因
    产品。
  • 政治:在政治领域,它用于跟踪政治观点,检测政府层面的声明和行动之间的一致性和不一致。它也可以用来预测选举结果!
  • 公共行为:情绪分析还用于监控和分析社会现象,以发现潜在的危险情况并确定博客圈的总体情绪。

安装:

  • Tweepy: tweepy 是官方 Twitter API 的Python客户端。
    使用以下 pip 命令安装它:
    pip install tweepy
  • TextBlob: textblob 是用于处理文本数据的Python库。
    使用以下 pip 命令安装它:
    pip install textblob

    此外,我们需要使用以下命令安装一些 NLTK 语料库:

    python -m textblob.download_corpora

    (语料库只不过是一个庞大而结构化的文本集。)

验证:
为了通过 Twitter API 获取推文,需要通过他们的 Twitter 帐户注册一个应用程序。请按照以下步骤操作:

  • 打开此链接并单击按钮:“创建新应用程序”
  • 填写申请详情。您可以将回调 url 字段留空。
  • 创建应用程序后,您将被重定向到应用程序页面。
  • 打开“密钥和访问令牌”选项卡。
  • 复制“消费者密钥”、“消费者秘密”、“访问令牌”和“访问令牌秘密”。

执行:

import re
import tweepy
from tweepy import OAuthHandler
from textblob import TextBlob
  
class TwitterClient(object):
    '''
    Generic Twitter Class for sentiment analysis.
    '''
    def __init__(self):
        '''
        Class constructor or initialization method.
        '''
        # keys and tokens from the Twitter Dev Console
        consumer_key = 'XXXXXXXXXXXXXXXXXXXXXXXX'
        consumer_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
        access_token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
        access_token_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXX'
  
        # attempt authentication
        try:
            # create OAuthHandler object
            self.auth = OAuthHandler(consumer_key, consumer_secret)
            # set access token and secret
            self.auth.set_access_token(access_token, access_token_secret)
            # create tweepy API object to fetch tweets
            self.api = tweepy.API(self.auth)
        except:
            print("Error: Authentication Failed")
  
    def clean_tweet(self, tweet):
        '''
        Utility function to clean tweet text by removing links, special characters
        using simple regex statements.
        '''
        return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])
                                    |(\w+:\/\/\S+)", " ", tweet).split())
  
    def get_tweet_sentiment(self, tweet):
        '''
        Utility function to classify sentiment of passed tweet
        using textblob's sentiment method
        '''
        # create TextBlob object of passed tweet text
        analysis = TextBlob(self.clean_tweet(tweet))
        # set sentiment
        if analysis.sentiment.polarity > 0:
            return 'positive'
        elif analysis.sentiment.polarity == 0:
            return 'neutral'
        else:
            return 'negative'
  
    def get_tweets(self, query, count = 10):
        '''
        Main function to fetch tweets and parse them.
        '''
        # empty list to store parsed tweets
        tweets = []
  
        try:
            # call twitter api to fetch tweets
            fetched_tweets = self.api.search(q = query, count = count)
  
            # parsing tweets one by one
            for tweet in fetched_tweets:
                # empty dictionary to store required params of a tweet
                parsed_tweet = {}
  
                # saving text of tweet
                parsed_tweet['text'] = tweet.text
                # saving sentiment of tweet
                parsed_tweet['sentiment'] = self.get_tweet_sentiment(tweet.text)
  
                # appending parsed tweet to tweets list
                if tweet.retweet_count > 0:
                    # if tweet has retweets, ensure that it is appended only once
                    if parsed_tweet not in tweets:
                        tweets.append(parsed_tweet)
                else:
                    tweets.append(parsed_tweet)
  
            # return parsed tweets
            return tweets
  
        except tweepy.TweepError as e:
            # print error (if any)
            print("Error : " + str(e))
  
def main():
    # creating object of TwitterClient Class
    api = TwitterClient()
    # calling function to get tweets
    tweets = api.get_tweets(query = 'Donald Trump', count = 200)
  
    # picking positive tweets from tweets
    ptweets = [tweet for tweet in tweets if tweet['sentiment'] == 'positive']
    # percentage of positive tweets
    print("Positive tweets percentage: {} %".format(100*len(ptweets)/len(tweets)))
    # picking negative tweets from tweets
    ntweets = [tweet for tweet in tweets if tweet['sentiment'] == 'negative']
    # percentage of negative tweets
    print("Negative tweets percentage: {} %".format(100*len(ntweets)/len(tweets)))
    # percentage of neutral tweets
    print("Neutral tweets percentage: {} % \
        ".format(100*(len(tweets) -(len( ntweets )+len( ptweets)))/len(tweets)))
  
    # printing first 5 positive tweets
    print("\n\nPositive tweets:")
    for tweet in ptweets[:10]:
        print(tweet['text'])
  
    # printing first 5 negative tweets
    print("\n\nNegative tweets:")
    for tweet in ntweets[:10]:
        print(tweet['text'])
  
if __name__ == "__main__":
    # calling main function
    main()

以下是运行上述程序时示例输出的样子:

Positive tweets percentage: 22 %
Negative tweets percentage: 15 %


Positive tweets:
RT @JohnGGalt: Amazing—after years of attacking Donald Trump the media managed
to turn #InaugurationDay into all about themselves.
#MakeAme…
RT @vooda1: CNN Declines to Air White House Press Conference Live YES! 
THANK YOU @CNN FOR NOT LEGITIMI…
RT @Muheeb_Shawwa: Donald J. Trump's speech sounded eerily familiar...
POTUS plans new deal for UK as Theresa May to be first foreign leader to meet new 
president since inauguration 
.@realdonaldtrump #Syria #Mexico #Russia & now #Afghanistan. 
Another #DearDonaldTrump Letter worth a read @AJEnglish 


Negative tweets:
RT @Slate: Donald Trump’s administration: “Government by the worst men.” 
RT @RVAwonk: Trump, Sean Spicer, et al. lie for a reason. 
Their lies are not just lies. Their lies are authoritarian propaganda.  
RT @KomptonMusic: Me: I hate corn 
Donald Trump: I hate corn too
Me: https://t.co/GPgy8R8HB5
It's ridiculous that people are more annoyed at this than Donald Trump's sexism.
RT @tony_broach: Chris Wallace on Fox news right now talking crap 
about Donald Trump news conference it seems he can't face the truth eithe…
RT @fravel: With False Claims, Donald Trump Attacks Media on Crowd Turnout 
Aziz Ansari Just Hit Donald Trump Hard In An Epic Saturday NIght Live Monologue

我们在计划中遵循以下 3 个主要步骤:

  • 授权推特 API 客户端。
  • 向 Twitter API 发出 GET 请求以获取特定查询的推文。
  • 解析推文。将每条推文分类为正面、负面或中立。

现在,让我们试着理解上面这段代码:

  • 首先,我们创建一个TwitterClient类。此类包含与 Twitter API 交互和解析推文的所有方法。我们使用__init__函数来处理 API 客户端的身份验证。
  • get_tweets函数,我们使用:
    fetched_tweets = self.api.search(q = query, count = count)

    调用 Twitter API 来获取推文。

  • get_tweet_sentiment 中,我们使用 textblob 模块。
    analysis = TextBlob(self.clean_tweet(tweet))

    TextBlob 实际上是一个建立在 NLTK 库之上的高级库。首先,我们调用clean_tweet方法使用一些简单的正则表达式从推文中删除链接、特殊字符等。
    然后,当我们通过tweet创建一个TextBlob对象时,textblob 库对文本进行以下处理:

    • 标记推文,即从文本正文中拆分单词。
    • 从标记中删除停用词。(停用词是在文本分析中不相关的常用词,如 I、am、you、are 等)
    • 对标记进行 POS(词性)标记,并仅选择重要的特征/标记,如形容词、副词等。
    • 将标记传递给情感分类器,该分类器通过为其分配 -1.0 到 1.0 之间的极性将推文情感分类为正面、负面或中性。

    以下是情感分类器的创建方式:

    • TextBlob使用电影评论数据集,其中评论已被标记为正面或负面。
    • 分别从每个正面和负面评论中提取正面和负面特征。
    • 训练数据现在由标记的正面和负面特征组成。这些数据是在朴素贝叶斯分类器上训练的。

    然后,我们使用TextBlob类的sentiment.polarity方法来获取-1 到1 之间的tweet 极性。
    然后,我们将极性分类为:

    if analysis.sentiment.polarity > 0:
           return 'positive'
    elif analysis.sentiment.polarity == 0:
           return 'neutral'
    else:
           return 'negative'
  • 最后,返回解析的推文。然后,我们可以对推文进行各种类型的统计分析。例如,在上面的程序中,我们试图找出有关查询的正面、负面和中性推文的百分比。

参考:

  • http://www.ijcaonline.org/research/volume125/number3/dandrea-2015-ijca-905866.pdf
  • https://textblob.readthedocs.io/en/dev/quickstart.html#sentiment-analysis
  • textblob.readthedocs.io/en/dev/_modules/textblob/en/sentiments.html