見出し画像

【Pythonコード】Twitter APIによりTwitter検索ツールを作成してみた①

どうも、こじまるです。

私はTwitterの運用にSocialDogを使っています。キーワードモニター機能が割と便利で利用しているのですが、無料アカウントの場合だとフォロー、いいね、リツイートの回数に制限があります。

SocialDogで有料アカウントになり余計な出費をするのは嫌なので、Twitter検索ツールを自作してみました。

1.はじめに

対象読者

・Twitter APIの使い方を知りたい方
・python・Twitter APIで何か作ってみたい方

この記事を見てわかること

・Twitter APIの使い方、実装方法

2. システム概要

要件定義

要件1. キーワードからTweetの検索ができること
要件2. 検索結果よりいいね、リツイートができること
要件3. ユーザが操作できること

環境構築
今回の実装では、下記を使用しました。

・フロントエンド : HTML, JavaScript
・サーバーサイド : Python(Flask)

HTML、JavaScriptではCDNでJQueryなどを取得しています。そのため、必要なものは特にありません。Pythonでは、pipで下記のパッケージをインストールしています。

pip install flask
pip install requests
pip install requests-oauthlib

3. 実装

要件を満たすために、下記の機能を実現する必要があります。

1.キーワードからTweetの検索
2.検索結果よりいいね、リツイートの実行

1. キーワードからTweetの検索

キーワードからTweetの検索の流れ

画像1

キーワードからTweetの検索の流れ
①Flaskへの検索依頼
②キーワードの検索依頼
③検索結果の表示依頼

①Flaskへの検索依頼

HTMLからFlaskに対して、POST /searchTweetという形で検索依頼を投げます。

Flaskでは、POST /searchTweetでルーティングできるように、app.routeで定義する必要があります。この関数ではリクエストの内容を解析し、リクエストから検索条件を取得しています。

@app.route('/searchTweet',methods=["POST"])
def getTweet():
   print('Enter getTweet')
   data = request.get_data().decode('utf-8')
   tmp,query = data.split('=')
   q = "q={}".format(query)
   lang = "lang=ja"
   result_type = "result_type=recent"
   count = "count=10"
   entities = "include_entities=true"

②Tweeter APIにキーワードの検索依頼
①で説明した、getTweetの続きになります。①で取得した検索条件に基づき、Twitter API : GET search/tweetsを使ってTwitterからTweetを取得します。

twitter = OAuth1Session(settings.CONSUMER_KEY,settings.CONSUMER_SECRET,settings.ACCESS_TOKEN,settings.ACCESS_TOKEN_SECRET)
endpoint = "https://api.twitter.com/1.1/search/tweets.json?{}&{}&{}&{}&{}".format(q,lang,result_type,count,entities)
res = twitter.get(endpoint)

Twitter API : GET search/tweetsGET statuses/lookupで取得したデータから、下記の情報を抽出し、リストに格納します。

画像2

ここで、retweeted_statusは引用なし(公式)リツイートの場合のみ取得できます。userオブジェクト・Tweetオブジェクトの内容はこちらの記事を参考にしました。

③検索結果の表示依頼

②で取得したuserオブジェクト・Tweetオブジェクトの情報を集積したリスト(tweet_list)をrender_templateメソッドの引数に指定します。

@app.route('/searchTweet',methods=["POST"])
def getTweet():
   ...
   print("Exit getTweet")
   return render_template('searchTweet.html', tweet_list=tweet_list)

今回は②で取得した検索結果を表示するために、tweet_listの配列数分ループさせるように実装しています。{{list.profile_image_url_https}}と記述することで、list内の要素にアクセスできます。

{% extends "layout.html" %}
{% block content %}
{% for list in tweet_list %}
<div class="twitter__block">
   <figure>
       <img src={{list.profile_image_url_https}} />
   </figure>
   ...
</div>
{% endfor %}
{% endblock %}

いいね、リツイートは、検索実行時のいいね、リツイートの状態に基づきON、あるいはOFFにして表示する必要があります。そのため、下記のようにlist.favoritedの値に応じて、spanタグのclass属性の値を切り替えるようにしました。

{% if list.favorited %}
   <span id={{list.tweet_id}} class="LikesIcon on">
       <i class="fas fa-heart LikesIcon-fa-heart heart">{{list.favorite_count}}</i>
   </span>
{% else %}
   <span id={{list.tweet_id}} class="LikesIcon">
       {% if list.favorite_count > 0 %}
           <i class="far fa-heart LikesIcon-fa-heart">{{list.favorite_count}}</i>    
       {% else %}
           <i class="far fa-heart LikesIcon-fa-heart"></i>
       {% endif %}
   </span>
{% endif %}

2.検索結果よりいいね、リツイートの実行

いいね・リツイートを行うために、下記のようにクリックイベントを使用します。(いいねとリツイートの実装はあまり変わらないため、今回はいいねの場合のみ説明します。)検索結果のあるツイートのいいねの状態がONであれば、いいねを外します。いいねの状態がOFFであれば、いいねを行います。

$('.LikesIcon').on('click', function() {
   let $btn = $(this);
   tweet_id = $btn.attr('id')
   // Likeボタンがonクラス持っていたら
   if ($btn.hasClass('on')) {
       $btn.removeClass('on');
       // 白抜きアイコンに戻す
       $btn.children("i").attr('class', 'far fa-heart LikesIcon-fa-heart');
       $.ajax({
           url: 'favorites',
           type:'DELETE',
           dataType: 'json',
           data : {'tweet_id' : tweet_id},
           timeout:3000,
       }).done(function(data) {
           if(data['favorite_count'] != 0)
               $btn.children("i").text(data['favorite_count'])
           else
               $btn.children("i").text("")  
       })
   } else {
       $btn.addClass('on');
       // ①アイコンを変更する
       // far fa-heart(白抜きアイコン)
       // ⇒ fas fa-heart(背景色つきアイコン)
       // ②アニメーション+アイコン色変更用のheartクラスを付与する
       $btn.children("i").attr('class', 'fas fa-heart LikesIcon-fa-heart heart');
       $.ajax({
           url: 'favorites',
           type:'POST',
           dataType: 'json',
           data : {'tweet_id' : tweet_id},
           timeout:3000,
       }).done(function(data) {
           $btn.children("i").text(data['favorite_count'])
       })
   }
});

JavaScript側で細々した操作をしたくないので、Ajaxでリクエストを送る先をFlaskにしています。Flaskでは、いいねを行う場合にはPOST favorites/createを実行し、いいねを外す場合にはPOST favorites/destroyを実行します。

@app.route('/favorites',methods=["POST"])
def setFavorites():
   twitter = OAuth1Session(settings.CONSUMER_KEY,settings.CONSUMER_SECRET,settings.ACCESS_TOKEN,settings.ACCESS_TOKEN_SECRET)
   tweet_id = request.form.get('tweet_id')
   endpoint = "https://api.twitter.com/1.1/favorites/create.json?id={}".format(tweet_id)
   res = twitter.post(endpoint)
   json_res = res.json()
   status = getStatus(tweet_id)
   return status

@app.route('/favorites',methods=["DELETE"])
def deleteFavorites():
   twitter = OAuth1Session(settings.CONSUMER_KEY,settings.CONSUMER_SECRET,settings.ACCESS_TOKEN,settings.ACCESS_TOKEN_SECRET)
   tweet_id = request.form.get('tweet_id')
   endpoint = "https://api.twitter.com/1.1/favorites/destroy.json?id={}".format(tweet_id)
   res = twitter.post(endpoint)
   json_res = res.json()
   status = getStatus(tweet_id)
   return status

Twitterのハートボタンのアニメーションはこちらの記事を参考にさせていただきました。

ソースコード
ソースコードはこちらに配置しています。
https://github.com/cojimaru3/management_tweet_tool

結果

GUIは簡易的なものしか用意できていませんが、要件を満たす振る舞いを実現できました。下記から実行結果をご確認ください。

4.まとめ

今回Twitter APIを使用して、Twitter検索ツールを作成してみました。自動実行だと実装が楽だったのですが、UIを持たせる仕様にしたかったので、それに余計に時間がかかってしまったと思います。また、普段使用しないTwitter APIの仕様を理解し、実装するのは結構難しいと感じました。

現状のツールでは、使用出来る機能が少なかったり、UIなども完全なものではないので今後改善を図りたいと思います。こちらの関連で何か出来上がりましたら、続編という形で掲載しますので、ご期待ください。


いいなと思ったら応援しよう!