MLAskを使って自分がTwitterでいいねをするツイートの傾向を分析する

#はじめに
　最近Twitterを活発にするようになりました。その中でよく#sarinatalkというタグについて検索し、いいねをしています。#sarinatalkは日向坂46の公式メッセージアプリでメンバーの潮紗理菜さんが発信したメッセージに対する、ファンのTwitterでの反応につくハッシュタグになります。今回はこのハッシュタグ#sarinatalkについて、自分がいいねをするツイートの傾向を分析しようと思います。

https://www.hinatazaka46.com/s/h46app/page_common/app_guide

#やったこと
・Twitterからtweepyを使ってデータ取集・ツイートの前処理
・MLAskでいいね有無それぞれに対するネガポジ分析

#データの収集・前処理
###TwitterAPIの登録
　Twitterからデータを収集するために、まずTwitterAPIを使うための登録を行いました。登録方法は以下を参考にしました。使用理由などを英語で記入しなければいけませんが、拙い中学レベルの英語でも大丈夫でした。
[Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ　※2019年8月時点の情報](https://qiita.com/kngsym2018/items/2524d21455aac111cdee#consumer-api-keys%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E6%83%85%E5%A0%B1%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9Fpython%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88)

###Tweepyでデータ収集・データの前処理
　登録しアクセスキーを取得したらTwitterAPIを動かすPythonライブラリのtweepyを使ってツイートを収集していきます。収集するツイートは以下の2つです。
・#sarinatalkがついているツイート
・自分がいいねしたツイート
これで#sarinatalkがついているツイートに対して、自分がいいねをしたかどうかのTrue/Falseのラベルをつけます。
　get_sarinatalk.pyで#sarinatalkの取得を行っています。TwitterAPIが1週間以上前のデータを取得できないため、定期的に取得しデータを増やしていきます。そのために既存のデータを読み込み、そこに新しいツイートを追加していきます。```get_tweet.get_tweet_by_search```で任意の検索ワード(今回は#sarinatalk)に該当するツイートを収集しています。また取得と同時にテキストの前処理として、fix_textで半角全角統一、絵文字の除去、改行を読点に変換を行っています。前処理については[こちら](https://qiita.com/konishi0125/items/f5a25046dbbb3fd231c8)を参照。また、```get_tweet.get_tweet_by_search```を```get_tweet.get_tweet_by_favorite```に変えることで、自分がいいねをしたツイートを取得しています。
　ツイートの取得は以下を参考にしました。
[Tweepyでツイートやいいねを一括取得する方法](https://qiita.com/lamrongol/items/3f14634594d388c96c03)

```Python:get_sarinatalk.py
import numpy as np
import pandas as pd
import get_tweet

# 既存の#sarinatalkリストの読み込み
data = pd.read_csv("./result/sarinatalk.csv")

# #sarinatalkの取得
out = pd.DataFrame(get_tweet.get_tweet_by_search("#sarinatalk", 2000), columns=["name", "text", "id"])

# 既存のデータ(data)と取得したデータ(out)をマージして重複を削除する
out = out.astype({"id": np.int64})
merge_data = pd.concat([out, data])
result = merge_data[~merge_data.duplicated()]

# #sarinatalkリストの保存
result.to_csv("./result/sarinatalk.csv", index=False)
```

```Python:get_tweet.py
import config
import tweepy
import time
import neologdn
import re

#search_keyで検索結果を取得
def get_tweet_by_search(search_key, get_num=1000):
    api = tweepy.API(auth_set())
    i=0
    out=[]
    for status in limit_handled(tweepy.Cursor(api.search_tweets, q=search_key).items(get_num)):
        t = fix_text(status.text)
        out.append([status.user.screen_name, t, status.id_str])
        print(i, status.created_at)
        i += 1
    return out

#自分のいいねを取得する
def get_tweet_by_favorite(get_num=1000):
    api = tweepy.API(auth_set())
    i=0
    out=[]
    for status in limit_handled(tweepy.Cursor(api.get_favorites).items(get_num)):
        t = fix_text(status.text)
        out.append([status.user.screen_name, t, status.id_str])
        print(i, status.created_at)
        i += 1
    return out

#tweepy用のトークン読み込み
def auth_set():
    CK = config.CONSUMER_KEY
    CS = config.CONSUMER_SECRET
    AT = config.ACCESS_TOKEN
    ATS = config.ACCESS_TOKEN_SECRET

    auth = tweepy.OAuthHandler(CK, CS)
    auth.set_access_token(AT, ATS)
    return auth

FIFTEEN_MINUTES = 16 * 60
#twitter取得制限が来たら処理を待つ関数
def limit_handled(cursor):
    while True:
        try:
            yield cursor.next()
        except tweepy.errors.TooManyRequests:
            print('Twitter rate limit')
            time.sleep(FIFTEEN_MINUTES)
        except StopIteration:
            print("fetch end")
            return None

#twitterから取得したテキストを成型する 全角半角統一、絵文字除去、改行を読点に変換
def fix_text(text):
    normalized_text = neologdn.normalize(text)
    text_without_url = re.sub(r"https?://[\w/:%#\$&\?\(\)~\.=\+\-]+", "", normalized_text)
    text_replace_newline = re.sub(r"\n", "。", text_without_url)
    text_delete_double_piriod = text_replace_newline.replace("。。","。")
    n = re.compile(r"[0-9a-zA-Z\u0023\u3040-\u30FF\u4E00-\u9FFF\u3001\u3002]")
    result = "".join(t for t in text_delete_double_piriod if n.search(t))
    return result

```

#MLAskによるネガポジ分析
　ネガポジ分析とは、文章がネガティブな内容かポジティブな内容かを判断する分析になります。MLAskの導入は以下を参考にしました。

https://qiita.com/yukinoi/items/ef6fb48b5e3694e9659c

　今回は#sarinatalkについていいねをしたツイートとしなかったツイートを分けて分析します。ただし、単に自分が見ておらずいいねがついていないツイートも含まれています。いいね有無それぞれでネガポジ分析をすることで、自分がいいねをするツイートの傾向をみてみます。
　ネガポジ分析のプログラムは以下の通りです。

```Python:analyze_morpheme.py
import pandas as pd
from mlask import MLAsk

#データの読み込み
data = pd.read_csv("./result/teaching_data.csv")
#MLAskの初期化
emotion_analyzer = MLAsk()

#カウントする変数の設定
no_count = 0
score = 0
pos = 0
nega = 0
neutral = 0
favo_pos = 0
favo_nega = 0
favo_neutral = 0

#ネガポジ分析
for index, sr in data.iterrows():
    text = sr["text"]
    if text == "":
        continue
    result = emotion_analyzer.analyze(text)
    if len(result) == 2:
        no_count += 1
        continue
    if result["orientation"] == "POSITIVE":
        if sr["favorite"] is True:
            favo_pos += 1
        elif sr["favorite"] is False:
            pos += 1
    elif result["orientation"] == "NEGATIVE":
        if sr["favorite"] is True:
            favo_nega += 1
        elif sr["favorite"] is False:
            nega += 1
    elif result["orientation"] == "NEUTRAL":
        if sr["favorite"] is True:
            favo_neutral += 1
        elif sr["favorite"] is False:
            neutral += 1

sum = pos + nega + neutral
favo_sum = favo_pos + favo_nega + favo_neutral
#結果の出力
print(f"no_count={no_count}, count={sum+favo_sum}")
print("=====number of tweet=====")
print(f"favorite : pos={favo_pos}, nega={favo_nega}, neutral={favo_neutral}")
print(f"no favorite : pos={pos}, nega={nega}, neutral={neutral}")
print("=====rate=====")
print(f"favorite : pos={round(favo_pos/favo_sum*100,1)}%, nega={round(favo_nega/favo_sum*100,1)}%,\
neutral={round(favo_neutral/favo_sum*100,1)}%")
print(f"no favorite : pos={round(pos/sum*100,1)}%, nega={round(nega/sum*100,1)}%, neutral={round(neutral/sum*100,1)}%")
```

#結果
　結果は以下になります。集まった1560ツイートの中で分析できたものが568ツイートでした。いいねをしたツイートはポジティブ87.3%、ネガティブ6.1%、ニュートラル6.6%となりました。これに対しいいねをしなかったツイートはポジティブ81.9%、ネガティブ10.9%、ニュートラル7.2%となりました。この結果から、ポジティブな内容のツイートをいいねしやすいことが分かりました。また、トータルとして#sarinatalkというタグに対してのツイートは8割以上がポジティブツイートであることが分かります。
　ただし判断できないツイートが約6割あり、精度の改善は必要であると思います。また、「このメッセージは泣ける」といった文章が「泣ける」という単語でネガティブと判断されていました。この文章は「泣けるほど良い」といったポジティブな内容になります。このようにポジティブやニュートラルと判断できる文章がネガティブに分類されている例もありました。

```
no_count=992, count=568
=====number of tweet=====
favorite : pos=303, nega=21, neutral=23
no favorite : pos=181, nega=24, neutral=16
=====rate=====
favorite : pos=87.3%, nega=6.1%,neutral=6.6%
no favorite : pos=81.9%, nega=10.9%, neutral=7.2%
```

#おわりに
　今回は自分がいいねをするツイートの傾向をネガポジ分析で見ました。ポジティブなツイートをいいねする傾向は感覚的にも合っており、想定通りの結果が得られたと思います。