PythonでTwitter botを作ってみた
この記事はかごんま🌋 Advent Calendar 2020の9日目の記事です。
初めまして鹿児島大学生の@hatuta_8_です。
今回は10月にpythonの勉強がてらつくったcontributter_rankingというTwitter botを紹介します。
概要
contributter_rankingとは
contributterを使っているユーザーの1日のcontribute数トップ3をメンション付きで自動ツイートする今回私が作ったbotです。
contributter?? contribute数??
となっている方もいると思うので以下解説します。
contributterとは
#contributter_reportでおなじみの毎日0時にGitHubのContribution数を呟いてくれるwebサービスです。
contributterはこちら
↓実際の#contributter_reportによるツイート
contributeとは
GitHubの1日の活動の記録を可視化することのできる機能
その見た目から「芝生」と呼ばれ、GitHub上で活動することを「草を生やす」と呼んでいます。
みなさんも一緒に芝生栽培活動しませんか?
開発の経緯
Contributterによってつぶやかれたツイートを自動で集計して毎日ランキングをツイートしてくれるbotがあったら人の頑張りが見えて面白そう、僕も頑張ろうってなるかもってことで作りました。
処理機構
- 昨日の#contributter_reportのついたツイート内のcontribution数とユーザーIDを取得
- contribution数を集計してランキング化
- ランキング上位3人をメンションしてcontribution数を記載し、自動ツイート
使用技術
- Python
- Twitter API
- cron
苦労したこと
Twitter API を使わせて頂く際の申請が面倒
以下のようにTwitter Developerにて英文でTwitter APIの利用目的を回答しないといけません。
- 「In English, please describe how you plan to use Twitter data and/or APIs. The more detailed the response, the easier it is to review and approve.(Twitter APIまたはTwitterデータの利用方法を教えて下さい)」
- 「Are you planning to analyze Twitter data?(ツイッターのデータを利用しますか?)」
利用する場合は「Yes」にして100文字以内で回答します。 - 「Will your app use Tweet, Retweet, like, follow, or Direct Message functionality?(アプリはツイート、リツイート、お気に入り、フォロー、ダイレクトメッセージを利用するか?)」
- 「Do you plan to display Tweets or aggregate data about Twitter content outside of Twitter?(Twitter以外のTwitterコンテンツに関するツイートを表示したり集計データを表示するか?)」
- 「Will your product, service or analysis make Twitter content or derived information available to a government entity?(あなたの製品・サービス,または分析によって,Twitterコンテンツまたは派生情報が政府機関が利用可能になりますか?)」
質問に回答して数日後にtwitter社から以下のようなメールがきます。
4つの質問に以下のように回答しました まだ質問あるんかい
数日後...
ついにTwitter APIが発行されました🎉🎉🎉
cronが実行されない!?
pcがスリープ状態だとどうやら実行されないみたい...
→macの設定で自動ツイートをさせたい時間にpcを自動で起動させることで解決しました。
実際のコード
準備
import json
import requests
import schedule
from datetime import datetime, date, timedelta
from requests_oauthlib import OAuth1Session
CONSUMER_KEY = '***************'
CONSUMER_SECRET = '***************'
ACCESS_TOKEN = '***************'
ACCESS_TOKEN_SECRET = '***************'
twitter = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
ツイートを取得する処理
- 昨日の日付を取得(一筋縄ではいかない)
today = datetime.today()
yesterday = today - timedelta(days=1)
yesterdays = datetime.strftime(yesterday, '%Y-%m-%d')
- #contributter_reportのツイートを取得
url = 'https://api.twitter.com/1.1/search/tweets.json'
max_id = -1
keyword='#contributter_report {yesterdays} exclude:retweets' .format(yesterdays=yesterdays) # #contributter_reportと昨日の日付
params ={
'count' : 100, # 取得するtweet数
'q' :keyword, # 検索キーワード
'max_id' : max_id #100件以上取得するために設定
}
tweets = [] #ここに取得したツイートを格納
- 100件以上ツイートを取得できるように繰り返し処理
while(True):
if max_id != -1:
params['max_id'] = max_id - 1
req = twitter.get(url, params = params)
if req.status_code == 200:
res = json.loads(req.text)
if res['statuses'] == []:
break
for tweet in res['statuses']:
tweets.append(tweet)
max_id = res['statuses'][-1]['id']
取得したツイートから欲しいデータだけ取り出し格納する処理
- ツイート内のユーザーネームとcontribution数をリスト化
#ユーザ名のリスト
list1=[]
s=0
for getname in tweets:
list1.append(tweets[s]['user']['screen_name'])
s=s+1
#contibution数のリスト
list3=[]
c=0
target = ":"
index = -1
for getfigure in tweets:
x=tweets[c]['text']
y=x[x.find(":"):]
list3.append(y)
c=c+1
- ユーザーネームとcontribution数をリストを辞書化
(ここは力技感が否めない...マサカリください)
#コロンを削除
list4=[]
d=0
for getnumber in tweets:
list4.append(list3[d][1:])
d=d+1
#後ろからスライスして数字のみにする
list5=[]
e=0
for get_c_number in tweets:
list5.append(list4[e][:-22])
e=e+1
#list1とlist2を辞書にする
rank_data=dict(zip(list1,list5))
- 上位3人のユーザーIDとcontribution数を格納
#contiributionが多い順に並び替える
rank_data2=sorted(rank_data.items(),key=lambda x:int(x[1]), reverse=True)
#上位3人を取得
top_contributor=rank_data2[0:3]
#上位3人のユーザIDとcontribution数を格納
no1=top_contributor[0]
no1_name=no1[0]
no1_number=no1[1]
no2=top_contributor[1]
no2_name=no2[0]
no2_number=no2[1]
no3=top_contributor[2]
no3_name=no3[0]
no3_number=no3[1]
実際にツイートする処理
twitter = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
url = 'https://api.twitter.com/1.1/statuses/update.json'
tweet_post = "👑 @{no1_name}さん contribution数{no1_number}\n 2 @{no2_name}さん contribution数{no2_number}\n 3 @{no3_name}さん contribution数{no3_number}" .format(no1_name=no1_name,no1_number=no1_number,no2_name=no2_name,no2_number=no2_number,no3_name=no3_name,no3_number=no3_number)
params = {'status': tweet_post}
twitter.post(url, params=params)
最後に
ここまで読んでいただき有り難うございました。
直感で書いた煩雑なコードなのでこれからリファクタリングしていこうと思います!
今回作ったbotをフォローしていただけると飛んで喜びます!
Discussion