読者です 読者をやめる 読者になる 読者になる

すてにゃん氏の技術ぶろぐ

技術っぽいこと書きます

Pythonでツイッターのエゴサ結果をSlackに流すbotを作る

その他

僕はよくツイッターをするんですけど、たまにメンション無しで「すてにゃん」ってつぶやく人が居て、でも1000人以上フォローしてるとすべてを監視するのは中々大変です。Slackなら1日中監視してるのでそっちに流すことにしました。PyConにも参加したことだしせっかくなので普段書かないPythonでやってみました。

Twitter Application Management でアプリを登録する

まずはTwitterの公式のとこでアプリの情報をいろいろと書いていってトークンなどを取得する必要があります。apps.twitter.com

何も難しいことをする必要はなく、アプリの名前、説明文、URLなどを入力すればおkです。
作成後、いくつかのタブが現れますが、僕はとりあえず Permissions って書いてある画面でアクセス権限を Read only にしました。今回はツイートを検索するだけなので。あとは Keys and Access Tokens ってタブであとで必要になってくるトークンが揃ってます。

REST API vs Streaming API

Twitterでアプリを作る場合考えないといけないことの一つは、REST API と Streaming API のどちら(もしくは両方)を使うべきかです。それぞれ詳しいことは公式のドキュメントに書いてあります。dev.twitter.com
dev.twitter.com

基本的にどういうものかというと、REST APIのほうは例えばツイートを検索する際、検索をするたびに GET search/tweets などを叩く必要があるのに比べて、Streaming APIの場合はずっと繋がってるので新着ツイートなどはドシドシ流れてくるという感じです。今回僕はStreaming APIのほうを使いました。なぜならREST APIのほうは気をつけないと制限に引っかかってAPI叩けなくなったり、実装があまりきれいにならないかなと思ったからです。

これだけ見ると常にStreaming API使いたくなるけど、例えばWi-Fiがない場所でツイッターをするときずっとツイート読み込み続けてるとデータ使われまくるので困りますよね。そういう点も多分考慮するべきなんでしょう(Twitterクライアントとか作ったことないけど)。

tweepy

僕がやりたかったのはぱぱっとエゴサしてSlackに流すbotを作るだけなので、とりあえずいい感じのPython向けのTwitterライブラリーを探しました。tweepyとかpython-twitterとかあるらしくて、特に深い理由はないけどtweepyというのを使ってみました。

Tweepy

とりあえずドキュメントにある Hello Tweepyというのをやってみて、端末にTLが流れていく様子をみましょう

# tweepy.org ドキュメントのHello Tweepy より
import tweepy

# consumer_key等はapps.twitter.comからとってきたものを使う
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

api = tweepy.API(auth)

public_tweets = api.home_timeline()
for tweet in public_tweets:
    print tweet.text

tweepy.Streaming

Hello Tweepyの例ではREST APIを使っているので、Streaming APIの場合は以下のドキュメントを参照しましょう
Streaming With Tweepy — tweepy 3.3.0 documentation

大体ドキュメントに書いてありますが、基本的にはStreamListenerを継承するクラスを作って、そこで on_status あたりにツイートが流れてくるのでそれをオーバーライドして好きに色々すればいいってことですね。というわけで、Hello TweepyのようなことをStreaming APIでやるとこんな感じになると思います。

import tweepy

# tweepy.StreamListener をオーバーライド
class MyStreamListener(tweepy.StreamListener):
    def on_status(self, status):
        print(status.text) #端末に表示するのみ

    def on_error(self, status_code):
        if status_code == 420:
            return False

def initialize():
    # consumer_keyなどは自分のに設定してください
    auth = tweepy.OAuthHandler("consumer_key", "consumer_secret")
    auth.set_access_token("access_token", "access_token_secret")
    api = tweepy.API(auth)
    startStream(api.auth)

def startStream(auth):
    myStreamListener = MyStreamListener()
    myStream = tweepy.Stream(auth = auth, listener=myStreamListener)
    myStream.userstream() #タイムラインを表示
    # myStream.filter(track=["#cats"]) #検索がしたい場合

def main():
    initialize()

if __name__ == "__main__":
    main()

今回はエゴサが目的だったので上のコードでもコメントで書きましたが、Streamのfilterというのを使えば検索が簡単にできます。そうすればエゴサ結果が端末に表示されていきます。あとはSlackに流すだけです。

Slackのincoming webhookの使い方

incoming webhookってなんぞやって感じですが、ここに色々書いてあります。
Incoming Webhooks | Slack

なんか要するに、リアルタイムに外からのデータをSlackに流し込んでやるぞいって感じですね。今回の目的にぴったし。Slackの流したいチャンネルのとこで、Add a service integrationっていうのをポチッとして、incoming webhookを選択すればOK。

先ほどのincoming webhookのドキュメントの最後にcurlの例が書いてあるんですが(以下の通りです)

curl -X POST --data-urlencode 'payload={"text": "This is posted to <#general> and comes from *monkey-bot*.", "channel": "#general", "username": "monkey-bot", "icon_emoji": ":monkey_face:"}' https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

だいたいこんなイメージでPOSTするだけでどうやら簡単にSlackに投稿できるらしいです。最後のhooks.slack.com/~~~のリンクはAdd a service integration→incoming webhookと選択したときに表示されるのでそれを使えばおkです。

で、Pythonでどうやんの?って思ったけど以下のように普通にできました。案外楽ちん

import json
import requests
def postToSlack(text):
    payload = {
        "channel": "#ego-search", 
        "username": "ego-search-master", 
        "icon_emoji": ":innocent:",
        "text": text
    }
    url = "https://hooks.slack.com/services/~~~~"
    payloadJson = json.dumps(payload)
    requests.post(url, data=payloadJson)

ってことで、先ほど端末にprintしてたのを、この関数を通せばSlackに流れるはずです。

herokuでデプロイ

herokuのことは結構前から知ってましたが、元々自分がWeb系じゃないってのもあって今まで触ったことがなかったです。ってことでアカウントを作って、以下の公式のドキュメントを読んでました
Getting Started with Python on Heroku | Heroku Dev Center

とりあえずわかったのはPythonの場合は他に Procfile と requirements.txt というのを用意すれば準備おkで、

  • heroku create hogehoge
  • git push heroku master
  • heroku ps:scale worker=1

とするだけでデプロイされるという予想以上に簡単だということ。ここまで敷居が低いとは思ってませんでした。

あとは heroku ps でプロセスを確認したり、 heroku logs --tail でログを確認したりできました。

ってことでツイッターのエゴサ結果をSlackに流すやつができたので好きなだけ「すてにゃん」とつぶやいてください〜
(数日後、そこにはエゴサ回避をする人々の姿が)

[雑談] 雨の日はきらいですがいつも行くゲーセンが雨の日100円2クレというのをやってるのでプラマイゼロという気分です