なんでやろうと思ったか
twitterのHOMEのタイムラインは下記のような状態になっています。
- プロモーション(広告)が出てくる
- 時系列順とは限らない
- 時間差で数時間前のツイートが一番上に来たりする
2番目と3番目は要は同じことなんですが、なんにせよtwitter側で恣意的に並べられています。
個人的にこれは気持ち悪いですし、プロモーションもよく出てきてノイズが大きいのがストレスでした。
「リストだったらプロモーションも出てこないし時系列順になるよ!」ということを
教えてもらい、全フォローユーザーが入っているリストを作成しようとしたのですが、
twitterには一括でリストにユーザー登録する方法がなかったので、この記事をまとめました。
事前準備
twitterのAPIを使って処理するので、Token取得が必要です。
けっこう手間かかるので、この記事では割愛しますが、下記の記事に詳しいです。
https://www.itti.jp/web-direction/how-to-apply-for-twitter-api/
twitterでアプリ登録して、下記を発行してください。
- CONSUMER_KEY
- CONSUMER_SECRET
- ACCESS_TOKEN
- ACCESS_TOKEN_SECRET
処理
ソースコードはこちらに格納してます
https://github.com/wonohe/twitter_create_follow_list
使い方
tweepyのインストール
twitterのAPI操作にtweepyを使用しています。
下記にてインストール
pip install -r requirements.txt
config修正
config.json.sample
をconfig.json
に変更して、各キーを登録してください。
キー | 説明 |
---|---|
SCREEN_NAME | 自分のtwitter表示名(例:@Starbucks_J) |
CONSUMER_KEY | twitterアプリのCONSUMER_KEY |
CONSUMER_SECRET | twitterアプリのCONSUMER_SECRET |
ACCESS_TOKEN | twitterアプリのACCESS_TOKEN |
ACCESS_TOKEN_SECRET | twitterアプリのACCESS_TOKEN_SECRET |
処理実行
cloneしたフォルダのルートにて下記実行
python main.py
解説
コードは下記のようになっています。
import datetime
import tweepy
import time
import json
# config
config = json.load(open('config.json', 'r'))
SCREEN_NAME = config['SCREEN_NAME']
CONSUMER_KEY = config['CONSUMER_KEY']
CONSUMER_SECRET = config['CONSUMER_SECRET']
ACCESS_TOKEN = config['ACCESS_TOKEN']
ACCESS_TOKEN_SECRET = config['ACCESS_TOKEN_SECRET']
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth, wait_on_rate_limit=True, timeout=180, retry_delay=10, retry_count=5)
#create list
now = datetime.datetime.now()
list = api.create_list(name=f'all-{now.strftime("%Y%m%d%H%M%S")}',mode='public')
print(f'list.id:{list.id}')
print(f'list.name:{list.name}')
#add following users to list
cursor = -1
error_usr = []
while cursor != 0:
itr = tweepy.Cursor(api.friends_ids, id=SCREEN_NAME, cursor=cursor).pages()
try:
for friends_ids in itr.next():
try:
user = api.get_user(friends_ids)
print(user.screen_name)
# 通信エラーユーザー対応。成功した場合は消す
error_usr.append(user.screen_name)
api.add_list_member(screen_name=user.screen_name, list_id=list.id, owner_screen_name=SCREEN_NAME)
error_usr.pop()
except tweepy.error.TweepError as e:
print(e.reason)
except ConnectionError as e:
print(e)
cursor = itr.next_cursor
print('通信エラー分対応')
# エラーがなくなるまで処理
while error_usr:
for name in error_usr:
try:
print(name)
api.add_list_member(screen_name=name, list_id=list.id, owner_screen_name=SCREEN_NAME)
error_usr.remove(name)
except tweepy.error.TweepError as e:
print(e.reason)
基本的にはtweepyAPIを使ってリスト作成→ユーザー登録、をしているだけですが、
いくつか気をつけるポイントがありました。
tweepyでAPIをコールする際の設定
twitterAPIをコールする際、回数制限があるので、tweepyでwait_on_rate_limit
はTrueにしておきましょう。デフォルトではFalseになっています。
api = tweepy.API(auth, wait_on_rate_limit=True, timeout=180, retry_delay=10, retry_count=5)
また、回数制限以外でもエラーになる場合があったので、timeoutとリトライ回数も長めにしてあります。
不明な通信エラーに対する対応
私のフォロー人数は144名でそんなに多くはないと思うのですが、処理の中で失敗してしまうユーザーが必ず何名かいました。エラーになるユーザーはバラバラで、144名に対してだいたい3〜5ユーザー程度です。
エラーは下記になるのですが、
Failed to send request: HTTPSConnectionPool(host='api.twitter.com', port=443): Max retries exceeded with url: /1.1/users/show.json?id=******* (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x10b1db410>: Failed to establish a new connection: [Errno 60] Operation timed out'))
connectionが張れなかった、というだけでよく分かりません。
この失敗した次のユーザーでは成功していたりしたので、回数制限でもなさそうです。
ググっても明確な原因が分からなかったので、エラー分だけリトライするようにしました。
ここでエラー分だけを配列に入れておいて、
# 通信エラーユーザー対応。成功した場合は消す
error_usr.append(user.screen_name)
api.add_list_member(screen_name=user.screen_name, list_id=list.id, owner_screen_name=SCREEN_NAME)
error_usr.pop()
この部分でエラーがなくなるまで登録処理をしています。
while error_usr:
for name in error_usr:
try:
print(name)
api.add_list_member(screen_name=name, list_id=list.id, owner_screen_name=SCREEN_NAME)
error_usr.remove(name)
except tweepy.error.TweepError as e:
print(e.reason)
まとめ
処理自体はそんなに複雑でもないのですが、twitterAPIが時々謎の挙動(突然エラーになる)など起きるのが少しややこしかったです。コード変更してないのに急に「その操作は許可してねえよ」って言われたりしたので、皆さんもテストするときは無茶しすぎないようにしましょうネ。
その他
こちらの記事を参考にさせていただきました。ありがとうございました。
https://note.com/j1ntube/n/n5a417a68178b