TwitterAPIをつかって人生を変えるTwitterBotをつくる
概要
- https://ntsa.connpass.com/event/211862/ のLTで発表する予定のTwitterBotです。
- 人の悪口を言っているようなツイートに対し、反応します。
背景
皆さん、人の悪口を言うのは好きですか?
かくいう私はとても好きで、昔は口を開けば人の悪口しか出てこないような、悪口人間でした。
もちろん、話すときは出来るだけおもしろおかしく話してたのですが、ある日気付いてしまったのです。
「話す側はいいけど、人の悪口聞いてるときあんま楽しくないな。」
これは、その人の悪口が面白くなかったからなのですが、自分が話してる内容が面白いかどうかは相手がどうとらえるかなわけで、そうすると自分が話している悪口ももしかしたら相手からするとつまらないのかもな。と。
笑いも取れてないし、自分の印象は下げるし、良いことないじゃん。
その日から私の人生のモットーは「人の悪口を言わない」になりました。
とはいいつつも、なんだかんだ言っちゃうときは結構あります。また、自分で悪口だと気付いてないことも多々あります。
「自分が悪口を言ったときに、教えてほしいなあ…」「自分で作るか。」
となったのが、今回TwitterBotを作った背景になります。
使い方
- https://twitter.com/doNotSpeakIll をフォローします
- フォローバックが返ってきます
- あなたが悪口をツイートすると、「人の悪口を言わない」とリプライが返ってきます
- 自然と自分が悪口に言っていることに気付き、悪口を言わなくなります。
- 悪口を言わなくなり素敵になったあなたの周りには、もう人の悪口を言うような人は一人もいません。
使ったものたち
- Python
- Tweepy
- oseti
コードの紹介(一部)
実際にAPIを触っている部分であったり、判定処理等はモジュール化しており、そこの関数を呼び出すようにしています。
# フォローしてくれた人にフォロー返す
follow_back()
# フォロー外した人はフォロー外す
unfollow()
json_open = open('./data/data.json', 'r')
json_load = json.load(json_open)
latest_tweet_id = json_load["latest_tweet_id"]
# ツイートの取得
# 前に取得し終わったツイートから取得し、重複しないようにする
for index, tweet in enumerate(fetch_tweet(count=200, since_id=latest_tweet_id, exclude_replies=True, include_rts=False)):
if index == 0:
# 最新のものに更新
json_load["latest_tweet_id"] = tweet.id
user_id = tweet.user.screen_name
if user_id not in json_load:
json_load[user_id] = {"favorite_count": 0,
"retweet_count": 0,
"tweet_count": 0,
"favorite_var": 0,
"retweet_var": 0,
"negative_count": 0}
# 外れ値でないならユーザの情報を更新
# 分散などを更新
if not is_outliers(tweet, json_load[user_id]):
json_load[user_id] = update_user_information(json_load[user_id], tweet)
# ユーザ情報を取得
user_info = json_load[user_id]
# 悪口をいっているようならリプライする
if is_bad_word_for_people(tweet, user_info):
reply_bad_people(tweet)
user_info["negative_count"] += 1
json_load[user_id] = user_info
with open('./data/data.json', mode='wt', encoding='utf-8') as file:
json.dump(json_load, file, ensure_ascii=False, indent=4)
技術紹介等
TwitterAPIの取得
-
https://www.itti.jp/web-direction/how-to-apply-for-twitter-api/
このへんを見てやりました。TwitterAPIの取得に関して書いてある記事は多々あるので、ぜひ調べてみてください。意外と面倒でした。
Tweepy
-
https://kurozumi.github.io/tweepy/api.html
日本語なのでかなり読みやすいです。APIリファレンスを読みながら実装しました。
例として、自作(ほぼ呼び出しているだけ)のタイムラインの取得のコードを下記に示します。
def fetch_tweet(count=20, since_id=None, max_id=None, trim_user=False, exclude_replies=False, include_entities=True, include_rts=True):
return api.home_timeline(count=count, since_id=since_id, max_id=max_id, trim_user=trim_user, exclude_replies=exclude_replies, include_entities=include_entities, include_rts=include_rts)
いろいろなパラメタがあるので、それぞれどのようなパラメタかはリファレンスを参照してほしいのですが、私が伝えたいことは、一行でタイムラインが簡単に取得できるということを伝えたいです。
他の機能として、Tweetしたり、フォローをしたり、フォロー解除したり、いいねしたり、RTしたりと、アプリで私たちが使うような機能は一通りできます。
詰まったポイントとして、Status
オブジェクトは、ツイートの情報を表しています。一見名前から分かり辛いので注意が必要です。また、screen_name
はユーザIDです。これも直感とはかなり異なったため少し戸惑いました。逆に、ユーザIDっぽく見えるid
ですが、これユーザ毎に一意に振り分けられた値であり、ユーザ名やユーザIDを変更しても変わらない値らしいです。もしユーザIDの変更にも対応したい場合にはこれを使いましょう。
oseti
東北大学の乾・鈴木研究室のページで公開されている日本語評価極性辞書を使ったSentiment Analysis (いわゆるネガポジ判定) ライブラリ
今回はこちらのライブラリを用いて悪口の判定をしました。判定については後述します。自分でネガポジの判定をするコードも書いたのですが、こちらの方が精度が良く感じたのでこちらを使わせていただきました。ありがとうございます。
文章を入力として、その文章のポジティブネガティブ度を-1~1の範囲で分析してくれます。
悪口の判定について
一番難しかったのはここです。ツイートが悪口かどうかは、二つの基準で判定しています。
- 中身にネガティブなワードが多いか?
- ツイートが伸びているか?
以下では、その選定理由について記述します。
中身にネガティブなワードが多いか?
日本語は難しいです。
前者のようなケースはとても判定し辛く、人間が見ても悪口なのかどうか分らないような悪口もあります。
そのため全てのケースを追うのは難しいと判断し、直接的なものに限定することにしました。すなわち、文章にネガティブなワードが入っているかどうか?で判定する。ということです。
しかし、ツイートにネガティブワードが多く入っている場合は人の悪口、そうでない場合は人の悪口ではない。という判定にすると、自分の自虐などにも反応してしまうことが考えられます。このBotを使うにあたって、リプライを送る、すなわち通知が来るというユーザへの負荷を与えることになります。そのため、今回は偽陽性の例を少なくしたかったので、条件を少し厳しくする必要がありました。追加したのが次の条件です。
ツイートが伸びているか?
ネガティブなツイートは二種類に分かれます。他人に向いているか、他人以外(自分)に向いているかです。そこで、そのようなツイートを眺めていた際に、私は気づきました。
「自虐のツイートって、あんまりおもしろくないし、いいねとかRTとかしづらいな」
つまり、ネガティブなツイートの中でも、対象が自分に向いているものは他人からのリアクションが少ない、と感じたのです。
今回はそれも条件に加えました。大雑把に言うと、「過去のツイートのいいね、RTの平均、分散から、伸びているツイートかどうか判定する」という処理を組み込んでいます。
最後に
TwitterBotは意外と簡単に作れました。APIがとても使いやすく、他にもいろいろなことが出来て楽しそうです。作りたいものがないけどプログラムを書きたい方には是非お勧めです。
P.S.
だそうです。
Discussion