Twitter で『フォロワーの中から相互フォロー状態になっていない人を
自動抽出してフォローするツール』を作成すべく、
フォロワーの情報を一括取得するコードを Python 3 で書いてみました。
tweepy を使用したコードはよく見かけたのですが、
今回は requests_oauthlib を使用しています。
Twitter API を使用する事前準備
Twitter API を使用するための準備を行います。
(Python はインストール済みであることを前提とします)
APIキーとアクセストークンの発行
Twitter API を使用するためには、APIキーとアクセストークンの発行が必要です。
まだ発行していない場合は、以下の記事を参考にしてこれらを発行してください。
発行は1時間程度で終わります。
requests_oauthlib モジュールのインストール
以下で紹介するサンプルコードを実行するにあたり、
requests_oauthlib モジュールが必要ですので、以下コマンドでインストールしておきます。
1 2 3 |
pip install requests_oauthlib |
インストール時の実行ログ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
> pip install requests_oauthlib Collecting requests_oauthlib Downloading requests_oauthlib-1.3.0-py2.py3-none-any.whl (23 kB) Requirement already satisfied: requests>=2.0.0 in c:\users\xxxxxxxxx\appdata\local\programs\python\python37\lib\site-packages (from requests_oauthlib) (2.21.0) Collecting oauthlib>=3.0.0 Downloading oauthlib-3.1.0-py2.py3-none-any.whl (147 kB) |■■■■■■■■■■■■■■■■| 147 kB 819 kB/s Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\users\xxxxxxxxx\appdata\local\programs\python\python37\lib\site-packages (from requests>=2.0.0->requests_oauthlib) (3.0.4) Requirement already satisfied: urllib3<1.25,>=1.21.1 in c:\users\xxxxxxxxx\appdata\local\programs\python\python37\lib\site-packages (from requests>=2.0.0->requests_oauthlib) (1.24.1) >requests_oauthlib) (2018.11.29) Installing collected packages: oauthlib, requests-oauthlib Successfully installed oauthlib-3.1.0 requests-oauthlib-1.3.0 |
|
|
Twitter API でフォロワー情報を取得するサンプルコード
以下、フォロワーの USER_ID と SCREEN_NAME をリストの辞書で
取得するサンプルコードです。
引数で与える screen_name は、フォロワー情報を取得したい Twitter ユーザー名を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# 必要なモジュールのインポート # 必要なモジュールのインポート from requests_oauthlib import OAuth1Session import json import copy # フォロワーの情報を取得する def get_twitter_follower_info(screen_name, consumer_key, consumer_secret, access_token, access_token_secret): # 認証情報を設定 twitter = OAuth1Session(consumer_key, consumer_secret, access_token, access_token_secret) cursor = -1 result_dict = {} result_list = [] # cursor が 0 になるまで繰り返し実行 while cursor != 0: # フォロワー情報取得のエンドポイントを設定 url = "https://api.twitter.com/1.1/followers/list.json" # 投稿情報を設定 params = {"screen_name" : screen_name, "cursor" : cursor} # GET の実行 try: response = twitter.get(url, params = params) # 取得したレスポンスを成形 data = response.json() user_list = data["users"] except Exception as e: print("フォロワー情報の取得に失敗しました。") else: for i in range(len(user_list)): result_dict["USER_ID"] = user_list[i]["id"] result_dict["SCREEN_NAME"] = user_list[i]["screen_name"] # 結果の辞書をリストへ格納 tmp_dict = copy.copy(result_dict) result_list.append(tmp_dict) cursor = data["next_cursor"] return result_list if __name__ == '__main__': get_twitter_follower_info("【screen_name】", "【consumer_key を入力】", "【consumer_secret を入力】", "【access_token を入力】", "【access_token_secret を入力】") |
Twitter API では、カーソルというページ単位で結果を取得します。
while文を使ってカーソルの値が 0 になるまで繰り返し取得しているのは
この対応をしているためです。
以下、公式マニュアル内の記載です。
To retrieve cursored results, you initially pass a cursor with a value of -1 to the endpoint. By default, an API endpoint that supports cursoring will assume -1 was passed as cursor if you do not provide one. The response to a cursored request will contain previous_cursor, next_cursor, previous_cursor_str and next_cursor_str. As is the case with most ID values in Twitter’s APIs, the _str values are provided for languages that cannot support large integers (e.g. JavaScript).
The next_cursor is the cursor that you should send to the endpoint to receive the next batch of responses, and the previous_cursor is the cursor that you should send to receive the previous batch. You will know that you have requested the last available page of results when the API responds with a next_cursor = 0.
Twitterの標準REST APIは、「カーソル」と呼ばれる手法を利用して、大きな結果セットにページ番号を付けます。
カーソルは結果をページ(カウント要求パラメーターで定義されるサイズ)に分割し、
これらのページを前後に移動する手段を提供します。
カーソル付きの結果を取得するには、最初に、値-1のカーソルをエンドポイントに渡します。
デフォルトでは、カーソルをサポートするAPIエンドポイントは、カーソルを指定しない場合、
-1がカーソルとして渡されたと想定します。カーソルリクエストへの応答には、previous_cursor、next_cursor、previous_cursor_str、およびnext_cursor_strが含まれます。
TwitterのAPIのほとんどのID値と同様に、_str値は大きな整数をサポートできない言語(JavaScriptなど)に提供されます。
next_cursorは、応答の次のバッチを受信するためにエンドポイントに送信する必要があるカーソルであり、
previous_cursorは、前のバッチを受信するために送信する必要があるカーソルです。
APIがnext_cursor = 0で応答すると、結果の利用可能な最後のページを要求したことがわかります。
フォロワーの数が極端に多いアカウントから情報を取得する場合、
上記コードをそのまま使用すると API の回数制限に引っかかる可能性があるため、
数ページ分の情報取得したら●分待機する、みたいな処理を入れる必要があるかもしれません。
→ API レート制限: 早見表API レート制限: 早見表
その他、コマンドの詳細については、以下のドキュメントを確認してください。
Twitter 開発者 ドキュメント日本語訳 GET followers/list
|
|
フォロワー情報取得のレスポンス一覧
上記コードでツイートした際、返却されるレスポンスの例を以下に記載します。
レスポンスには、フォロワーさんの情報はもちろん、フォロワーさんが直近で
ツイートした内容なども含まれています。
サンプルコード内でも実施していますが、json 形式で受け取ることで、
レスポンスから情報を引き抜くことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
{ "users": [ { "id": XXXXXXXXXX, "id_str": "XXXXXXXXXX", "name": "フォロワーさんの名前", "screen_name": "フォロワーさんのスクリーン名", "location": "フォロワーさんの住所", "description": "フォロワーさんの自己紹介文", "url": null, "entities": { "description": { "urls": [] } }, "protected": false, "followers_count": 189, "friends_count": 325, "listed_count": 0, "created_at": "Sun Dec 14 09:46:50 +0000 2014", "favourites_count": 3793, "utc_offset": null, "time_zone": null, "geo_enabled": false, "verified": false, "statuses_count": 2345, "lang": null, "status": { "created_at": "Mon May 11 06:36:09 +0000 2020", "id": XXXXXXXXXXXXXXXXXXXX, "id_str": "XXXXXXXXXXXXXXXXXXXX", "text": "フォロワーさんのツイートした文章", "truncated": false, "entities": { "hashtags": [], "symbols": [], "user_mentions": [ { "screen_name": "XXXXXXXXXX", "name": "フォロワーさんがリツイートした方の情報", "id": フォロワーさんがリツイートした方のID, "id_str": "フォロワーさんがリツイートした方のID", "indices": [ 3, 14 ] } ], "urls": [] }, "source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>", "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "geo": null, "coordinates": null, "place": null, "contributors": null, "retweeted_status": { "created_at": "Mon May 11 06:31:07 +0000 2020", "id": XXXXXXXXXXXXXXXXXXXX, "id_str": "XXXXXXXXXXXXXXXXXXXX", "text": "フォロワーさんのリツイート元文章", "truncated": false, "entities": { "hashtags": [], "symbols": [], "user_mentions": [], "urls": [] }, "source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone</a>", "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "geo": null, "coordinates": null, "place": null, "contributors": null, "is_quote_status": false, "retweet_count": 29, "favorite_count": 85, "favorited": false, "retweeted": false, "lang": "ja" }, "is_quote_status": false, "retweet_count": 29, "favorite_count": 0, "favorited": false, "retweeted": false, "lang": "ja" }, "contributors_enabled": false, "is_translator": false, "is_translation_enabled": false, "profile_background_color": "C0DEED", "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile": false, "profile_image_url": "http://pbs.twimg.com/profile_images/XXXXXXXXXXXXXXXXXX.jpg", "profile_image_url_https": "https://pbs.twimg.com/profile_images/XXXXXXXXXXXXXXXXXX.jpg", "profile_link_color": "1DA1F2", "profile_sidebar_border_color": "C0DEED", "profile_sidebar_fill_color": "DDEEF6", "profile_text_color": "333333", "profile_use_background_image": true, "has_extended_profile": false, "default_profile": true, "default_profile_image": false, "following": false, "live_following": false, "follow_request_sent": false, "notifications": false, "muting": false, "blocking": false, "blocked_by": false, "translator_type": "none" } ], "next_cursor": 0, "next_cursor_str": "0", "previous_cursor": 0, "previous_cursor_str": "0", "total_count": null } |
以上、参考にしてみてください^^
コメント