Twitter APIを用いて好きな画像にWordCloud

## はじめに
前回、前々回と取り組んできた最終章となります。
前々回、Matplotlibでグラフの作成をしました。
前回、WordCloudを使い、テキストファイルから可視化を行いました。

今回はTwitter APIを使って抽出したテキストを好きな画像に書き込みます。

## 環境
```
macOS Ventura 13.0.1
Google Colaboratory
```

## Twitter APIの取得
Twitterにログインして、下記のURLにアクセスしてTwitter Divelopersのアカウントを作成します。
https://developer.twitter.com/en/apps/
登録は全部英語です。
翻訳機能などを使えば登録できると思います。

アカウントを作成したらアクセストークンなどもそのまま設定しましょう。
仮に忘れてしまった場合やメモし忘れた場合でもすぐ再設定出来ます。
4つのトークンやキーなどを下記の＊の箇所に入力して使います。
```python
config = {
    "CONSUMER_KEY": "****************",
    "CONSUMER_SECRET": "*********************************",
    "ACCESS_TOKEN": "****************************************",
    "ACCESS_TOKEN_SECRET": "***************************:"
}
```
![スクリーンショット 2022-12-23 22.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741139/e447aecb-9ed6-686a-6f97-cfb1ad53b88f.png)


## ゴール
TwitterのAPIを叩いて「World Cup」と検索します。ワールドカップの決勝の結果が出たあたりの3:30~4:00でツイートを抽出します。
今回は少ないですが、ツイートを1000件取得としています。


## APIからの取得
```python
import json
import datetime
from dateutil.parser import parse as dateutil_parser
from requests_oauthlib import OAuth1Session

# アクセストークン等を設定
config = {
    "CONSUMER_KEY": "****************",
    "CONSUMER_SECRET": "*********************************",
    "ACCESS_TOKEN": "****************************************",
    "ACCESS_TOKEN_SECRET": "***************************:"
}

class TwitterApi:
    def __init__(self, config):
        self.start_session(**config)
        # search api の url
        self.url_search = "https://api.twitter.com/1.1/search/tweets.json?tweet_mode=extended"

    def start_session(self, CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET):
        # OAuth認証
        self.api = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

    def search(self, 
        search_word,# 検索したいワード
        since=None, # ツイート期間の絞りこみ（いつから、日本時間で入力）
        until=None, # ツイート期間の絞りこみ（いつまで、日本時間で入力）
        max_tweets = 1000 #最大検索数 どのくらいのツイート数を集めたいか。
    ):
        def print_tweet(tweet):
            print( tweet.get("full_text").replace("\n", " ") )
            

        def perser(index, tweet, hours=9): #hours=9 で日本時間への変換を行なっている。
            dt = dateutil_parser(tweet.get("created_at")) + datetime.timedelta(hours=hours)
            tweet["created_at"] = dt
            return tweet, dt

        # 日付関連の変数
        since_dt = dateutil_parser(since+"+00:00")
        until_params = dateutil_parser(until+"+00:00").strftime('%Y-%m-%d_%H:%M:%S')+"_JST"
        
        max_api_call = max_tweets // 100 + 1 # APIを叩く回数


        # 検索実行
        tweets = []
        max_id = None
        index = 0
        params = {"q": search_word, "count": 100, "result_type": "recent", 
                  "exclude": "retweets", "until": until_params}
        for n in range(max_api_call):
            # APIを叩く（最大100件）
            req = self.api.get(self.url_search, params=params)
            if req.status_code == 200: #検索結果を得られた場合
                #検索を取得
                timeline = json.loads(req.text)["statuses"]
                if len(timeline) == 0:
                    break
                for k, tweet in enumerate(timeline):
                    max_id = int(tweet["id"]) - 1
                    # ツイートの日時を取得
                    tweet_mod, dt = perser(index, tweet)
                    # ツイートが期間内のものか確認
                    if dt >= since_dt:
                        tweets.append(tweet_mod)
                        print_tweet(tweet_mod)
                        index += 1
                        params["max_id"] = max_id 
                    else:
                        max_id = None
                print()
                if max_id is None:
                    break
            else:
                print("Error")
                
        return tweets

if __name__=='__main__':

    # 1. インスタンス作成
    twitter_api = TwitterApi(config)
    
    # 2. 検索を実行し、結果が格納されたリストを得る
    tweets = twitter_api.search(
        "World Cup",
        since="2022-12-19 3:３０:00",
        until="2022-12-19 4:00:00"
    )
```


## API実行結果
画像は一部ですが、今回は1000件分のツイートを取得しています。
![スクリーンショット 2022-12-23 1.08.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741139/ecc1e668-f36b-304d-41e7-48653cf40cc4.png)

この実行結果をWorldCup.txtとして使っていきます。

## WordCloud
WordCloudに関しては前回のも参考にしてもらえればと思いますが、今回は画像に文字を入れていくので少し変えています。
今回のWordCloudの使い方としては、画像の白以外に文字が入力されるようになっています。
事前準備としてお好きな画像を用意して"worldcup_logo.jpg"のところに当てはめてもらえれば好きな画像で作成することが可能です。

```python
from google.colab import drive
drive.mount('/content/drive')

cd drive/My Drive

cd Twitter_API

from wordcloud import WordCloud
from matplotlib import pyplot as plt
from PIL import Image
import numpy as np

with open("WorldCup.txt", "r", encoding="utf-8")as f:
     text=f.read()
        
mask_array = np.array(Image.open('worldcup_logo.jpg'))

wordcloud =WordCloud( 
    mask=mask_array, 
    background_color="white", 
    contour_width=5, 
    contour_color='blue').generate(text)
plt.imshow(wordcloud)
```

## ツイートを可視化
今回はワールドカップっぽい画像にこだわってロゴを元に作成したのですが、なかなか画像の選択がうまくいかなくてちょっとわかりにくくなってしまった気がします。
![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741139/fe855751-c8d5-e263-ee89-a2e10a906323.png)

本当であれば下記のような形でお見せできれば良かったのですが。
こちらはアメフトのヘルメットを元に作成しました。
![sb_rams.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741139/7642c2d2-9118-4cd9-3ade-eaffa6ead097.png)

## まとめ
Twitter APIは他にも使い方がありますが、私もまだまだ理解が浅いので他にもできることを今後やっていきたいですね。
TwitterではURLを貼り付ける人も多いので、不要なワードは絞る処理をいれるともっといい結果が得られるのかなと思います。
個人的にはこうやって可視化するの面白いと思ってるので色々試してみたいです。