PythonでTwitter botを作ってみた

公開:2020/12/06
更新:2020/12/08
6 min読了の目安(約5800字TECH技術記事

この記事はかごんま🌋 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があったら人の頑張りが見えて面白そう、僕も頑張ろうってなるかもってことで作りました。

処理機構

  1. 昨日の#contributter_reportのついたツイート内のcontribution数とユーザーIDを取得
  2. contribution数を集計してランキング化
  3. ランキング上位3人をメンションしてcontribution数を記載し、自動ツイート

使用技術

  • Python
  • Twitter API
  • cron

cronはpcでファイルを定時に自動実行させるためのコマンドです

苦労したこと

Twitter API を使わせて頂く際の申請が面倒

以下のようにTwitter Developerにて英文でTwitter APIの利用目的を回答しないといけません。

  1. 「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データの利用方法を教えて下さい)」
  2. 「Are you planning to analyze Twitter data?(ツイッターのデータを利用しますか?)」
    利用する場合は「Yes」にして100文字以内で回答します。
  3. 「Will your app use Tweet, Retweet, like, follow, or Direct Message functionality?(アプリはツイート、リツイート、お気に入り、フォロー、ダイレクトメッセージを利用するか?)」
  4. 「Do you plan to display Tweets or aggregate data about Twitter content outside of Twitter?(Twitter以外のTwitterコンテンツに関するツイートを表示したり集計データを表示するか?)」
  5. 「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')

3行目のコードで日付型→文字列への変換している

 

  • #contributter_reportのツイートを取得

Twitter APIの制限で一度に取得できるツイートは100件までなのでcountを100としている

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件以上ツイートを取得できるように繰り返し処理

100件の同じツイートを取得し続けないようにmax_idを付与してツイートを続きから取得できるようにしている

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をフォローしていただけると飛んで喜びます!