Twitter APIによりTwitter検索ツールを作成してみた
どうも、現役エンジニアのこじまるです。
今回はTwitter管理のために、Twitter APIを使用してTwitter検索ツールを自作します。
私はTwitterの運用にSocialDogを使っています。キーワードモニター機能が割と便利で利用しているのですが、無料アカウントの場合だとフォロー、いいね、リツイートの回数に制限があります。
SocialDogで有料アカウントになり余計な出費をするのは嫌なので、Twitter検索ツールを自作してみました。
Twitter検索ツール作成
環境構築
今回の実装では、下記を使用しました。
- フロントエンド : HTML, JavaScript
- サーバーサイド : Python(Flask)
HTML、JavaScriptではCDNでJQueryなどを取得しています。そのため、必要なものは特にありません。Pythonでは、pipで下記のパッケージをインストールしています。
pip install flask pip install requests pip install requests-oauthlib
実装
キーワードからTweetの検索
①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/tweetsとGET statuses/lookup*1で取得したデータから、下記の情報を抽出し、リストに格納します。
【userオブジェクト】
名前 | 内容 |
name | ネーム |
screen_name | スクリーンネーム |
id | 数値型のユーザーID |
profile_image_url_https | プロフィール画像のSSL用のURL |
【Tweetオブジェクト】
名前 | 内容 |
id_str | 文字列型のツイートID |
text | ツイートの本文 |
created_at | Tweetが投稿された日時 |
favorited | いいねされているかどうかの状態 |
favorite_count | いいねされた数 |
retweeted | リツイートされているかどうかの状態 |
retweet_count | リツイートされた数 |
retweeted_status | 元のツイートの情報 |
ここで、retweeted_statusは引用なし(公式)リツイートの場合のみ取得できます。
userオブジェクト・Tweetオブジェクトの内容はこちらの記事を参考にしました。
syncer.jp
③検索結果の表示依頼
②で取得した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 %}
検索結果からいいね、リツイートを行う
いいね・リツイートを行う
いいね・リツイートを行うために、下記のようにクリックイベントを使用します。(いいねとリツイートの実装はあまり変わらないため、今回はいいねの場合のみ説明します。)検索結果のあるツイートのいいねの状態が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のハートボタンのアニメーションは下記記事を参考にさせていただきました。
yuyauver98.me
コード
コード全文はGithubにアップロードしているので、こちらからご確認ください。
github.com
結果
SocialDogのキーワードモニターを使っているのですが、無料プランではいいね・Retweet回数が制限されます。
— cojimaru (@cojimaru3) March 20, 2021
なので、検索ワードに基づき、Tweetを検索するツールを自作しました。
ツール上でTweetの検索→いいね・Retweetボタンを押下→アカウント上でRetweetが反映されていることを確認してます。 pic.twitter.com/2b6WpMHqtr
まとめ
今回Twitter APIを使用して、Twitter検索ツールを作成してみました。自動実行だと楽だったのですが、UIを持たせる仕様にしたかったので、それに余計に時間がかかってしまったと思います。また、普段使用しないTwitter APIの仕様を理解し、実装するのは結構難しいと感じました。
現状のツールでは、使用出来る機能が少なかったり、UIなども完全なものではないので今後改善を図りたいと思います。こちらの関連で何か出来上がりましたら、続編という形で掲載しますので、ご期待ください。
pythonでTwitter APIを使用した自動投稿の記事も書いていますので、ぜひ見てください。
cojimaru-chan.hatenablog.com