【python】TwitterAPIを用いてオーディンション番組の投票数を取得する

#動機
自分が最近見ているオーディション番組（PRODUCE 101 JAPAN SEASON2）では一般投票により最終的なデビューメンバーが決まります。投票はオーディション番組のWebサイトで行います。また誰に投票したかを投票後にTwitterに投稿できる機能があります。
誰が人気かを把握するためにTwitterAPIを用いて投票数を集計したいと思います。

本記事と同様の趣旨でyoutubeのデータを取得する記事も投稿致しましたので、もし良かったら見てください。
[【python】YoutubeAPIを用いてオーディンション番組動画の情報を取得する](https://qiita.com/zawakou_dx/items/bbad47abd9d2ca2525d9)

#開発環境
python3.9.0
tweepy3.10
Mac OS Mojava 10.14.6

#TwitterAPIを使用する
本記事ではAPIの使用方法の説明は省略します。
自分は以下のページを参考にしました。
>https://zenn.dev/kumamoto/scraps/fac96d402a589ed86283

APIの仕様等はtweepy Documentationを参照致しました。
>https://docs.tweepy.org/en/v3.10.0/index.html

```python
import tweepy

    api_key=os.environ.get('API_KEY')
    api_secret=os.environ.get('API_SECRET')
    acc_token=os.environ.get('ACCESS_TOKEN')
    acc_secret=os.environ.get('ACCESS_TOKEN_SECRET')

    #twitter objectの生成
    auth = tweepy.OAuthHandler(api_key, api_secret)
    auth.set_access_token(acc_token, acc_secret)
    api = tweepy.API(auth,wait_on_rate_limit=True, 
                     wait_on_rate_limit_notify=True, timeout=1000)
```

・wait_on_rate_limit 
　　APIの利用制限の引っかかったときに自動で待機してくれる
・wait_on_rate_limit_notify
   利用制限に引っかかった時にどれほど待機するのか教えてくれる
・timeout
   ツイッターから応答をどれだけ待つか

今回は、大量のツイートを取得するため上記のパラメータを設定しています。
ただ、自分の場合には利用制限に引っかからないようにコードを実装しました。
ちなみに検索の利用は15分間で180回を超えると制限がかかります。

#ツイートを検索する
今回対象とするツイート例です。webサイトから以下のフォーマットで投稿されます。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">国民プロデューサーが決めるボーイズグループオーディション。国民投票＆練習生プロフィール<br> <a href="https://t.co/6B7Lg4kKTz">https://t.co/6B7Lg4kKTz</a> <a href="https://twitter.com/hashtag/PRODUCE101JAPAN2?src=hash&amp;ref_src=twsrc%5Etfw">#PRODUCE101JAPAN2</a> <a href="https://twitter.com/hashtag/LETMEFLY?src=hash&amp;ref_src=twsrc%5Etfw">#LETMEFLY</a></p>&mdash; 🍼 (@amattareeeee) <a href="https://twitter.com/amattareeeee/status/1398005316806078465?ref_src=twsrc%5Etfw">May 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

よって、検索ワードは「国民投票＆練習生プロフィール exclude:retweets」
RTは除きます。

誰に投票したかはツイート内のURLから判別します。以下がURL例です。
>https://gyao.yahoo.co.jp/specials/produce101-vote?id=C004%2CC036&source=external.twitter.vote

URLのid=直後にあるC004とC036が参加者に一意に割り当てられたIDです。
下記の流れで集計します。
1.ツイート検索
2.ツイート取得、URL解析
3.投票数カウント

以下が実装です。

```python
#引用RTの排除、現在の仕様だとRTは元々検索から除外
word = ["国民投票&練習生プロフィール exclude:retweets"]
#投票数
num_of_all_votes = 0
try:
        for tweets in tweepy.Cursor(api.search, q=word,
                               result_type="recent", lang='ja',
                               tweet_mode='extended',
                               include_entities=True).pages():
            for tweet in tweets:
                try:
                    str_url=tweet.entities["urls"][0]["expanded_url"]
                    #URLから参加者のID抽出
                    for m in re.finditer('C[\d]{3}', str_url):
                        if (bool(m) == False):
                            break
                        #辞書型にデータを格納していきます
                        vote[m.group()] += 1
                        num_of_all_votes += 1
                except Exception as e:
                    print(e)
                    continue
            #15分間180回の制限を超えないように調整
            time.sleep(5)
    except Exception as e:
        print(e)
        print("取得ツイート数："+str(num_of_all_votes))
        file.close()
    print("取得ツイート数："+str(num_of_all_votes))
```

>for tweets in tweepy.Cursor(api.search, q=word,

tweepyのCursorを用いてツイートを取得します。
Cursorではitems()を用いて１ツイートずつ取得する方法と
pages()を用いて1ページ(15ツイート)ずつ取得する方法の２種類がありますが
利用制限を考慮して1回のリクエストで1ページを取得しています。
取得したツイートの情報はStatusオブジェクトという形でまとまっています。
Statusオブジェクトに何が格納されているかを以下のブログを参照しました。
>https://www.virtual-surfer.com/entry/2018/04/15/190000

<br>
>result_type="recent"

result_typeは最新の投稿から取得するためにrecentを指定しています。他にも人気順のpopular,時系列、人気のどちらも考慮したmixedがあります。

>tweet_mode='extended',include_entities=True

URLの取得が必須なので省略されたURL、ツイートを取得するパラメータを設定します。

>time.sleep(5)

利用制限に引っかからないように１ページ取得毎に５秒間待機します。
tweepy.API()でwait_on_rate_limitを指定すると自動で待機してくれるのですが、
その方法で実行したら何度かタイムアウトしてしまったのでアクセス頻度をコントロールするようにしました。

#結果
実行した結果、以下のように得票数を取得できました。
今回は１週間分のツイートを検索しました、この結果は１週間分(5/19~5/26)のものです。
１週間以上前のツイートは公式によるとdeveloper accountでプレミア契約しないといけない、課金しないといけないらしいです。（ちょっと調べた感じ課金しなくても１週間前以上のツイートを検索する方法があるらしい）

>村松 健太 434
木村 柾哉 409
田島 将吾 384
寺尾 香信 319
仲村 冬馬 307
藤牧 京介 293
大久保 波留 284
西島 蓮汰 273
飯沼 アントニー 263
許 豊凡 251
尾崎 匠海 241
後藤 威尊 238
佐野 雄大 231
篠原 瑞希 230
小林 大悟 221
西 洸人 220
髙塚 大夢 202
松田 迅 197
四谷 真佑 195
太田 駿静 195
中野 海帆 193
小堀 柊 193
井筒 裕太 191
内田 正紀 176
笹岡 秀旭 163
池﨑 理人 127
小池 俊司 116
福田 翔也 115
栗田 航兵 109
髙橋 航大 105
森井 洸陽 87
松本 旭平 80
福田 歩汰 77
ヴァサイェガ 光 76
平本 健 73
阪本 航紀 62
飯吉 流生 59
テコエ 勇聖 55
大和田 歩夢 45
上田 将人 11