Python と Twitter API でリツイートしたユーザーの情報を取得する

Python と Twitter API でリツイートしたユーザーの情報を取得する

エンジニアブログ

投稿日:2018/04/04 | 最終更新日:2018/09/14

初めまして、小林さとると申します。1月よりシステムソリューション事業部でインターンシップに参加しております。開発業務の中で、初めて Twitter API に触れたので、参考になった記事や自分のつまってしまったところなどをまとめました。
至らない点が多々あるかと思いますが、よろしくお願いいたします。

やること

Mac のターミナルと Python3 、 Twitter API を用いて、リツイートしたユーザの情報を取得します。リツイートされたツイートの ID を API にリクエストし、リツイート ID 、リツイートした人のユーザ ID 、リツイートした時間を CSV 形式で格納します。

準備

Homebrew から Python3 をインストールします。
brew を入れてない場合はパッケージ管理システム Homebrew という記事を参考にしてください。
ターミナルで下記のコマンドを実行するとインストールされます。

$ brew install python3

OAuth認証

Twitter API を使うには OAuth 認証が必要です。
Python で Twitter から情報収集 ( Twitter API 編) という記事を参考にターミナルから OAuth 認証に必要なライブラリをインストールします。

$ pip install requests requests_oauthlib
Exception:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 342, in run

記事にあったコマンドだとエラーが出てしまいました。早速つまりました。自分は Python3 を入れていた環境だったので次のコマンドで成功しました。

$ pip3 install requests_oauthlib

Twitter API Key の取得

Twitter API の OAuth 認証を行うには以下の4つの key が必要なので取得します。

  • Consumer key
  • Consumer secret
  • Access token
  • Access token secret

Twitter にログインして、 Twitter アプリケーションの作成(Consumer key、Consumer secret、Access token、Access token secret の確認方法)という記事を参考に取得しましょう。

ツイート ID の取得方法

Twiiter で取得したいツイートをクリックします。
スクショ
赤線内の [948499059471392769] がこのツイートの ID です。 Twitter の URL は以下のような構造になっています。
https://twitter.com/{スクリーンネーム}/status/{ツイートID}
タイムラインのツイート ID をすべて取得したい場合は、 Tweepy でツイートを取得という記事を参考に取得しましょう。

実行コード

#coding:utf-8
#!/usr/bin/env Python
from requests_oauthlib import OAuth1Session
import json
import csv
import collections as cl
import datetime,sys,time
'''
OAuth認証
'''
def request_authorization (**url_and_params):
    twitter = OAuth1Session(url_and_params['ck'], url_and_params['cs'], url_and_params['at'], url_and_params['ats'])
    if('params' in url_and_params):
        request_result = twitter.get(url_and_params['request_url'],params=url_and_params['params'])
    else:
        request_result = twitter.get(url_and_params['request_url'])
    return request_result
'''
API制限をチェックし、制限解除までスリープ
'''
def sleep_until_api_limit(api_response):
    sec = int(api_response.headers['X-Rate-Limit-Reset']) - time.mktime(datetime.datetime.now().timetuple()) #UTCを秒数に変換
    sec += 60.0#念のため1分追加
    print(str(sec)+"秒待機")
    time.sleep(sec)
#取得した4つのkeyをここに差し込みます。
CK = "XXXXXXXXXXXXXXXXXXXXXX" #Consumer key
CS = "XXXXXXXXXXXXXXXXXXXXXX" #Consumer secret
AT = "XXXXXXXXXXXXXXXXXXXXXX" #Access token
AS = "XXXXXXXXXXXXXXXXXXXXXX" #Access token secret
global twitter#メソッド内で再認証を行うため
twitter = OAuth1Session(CK, CS, AT, AS)#認証処理。数時間すると認証が切れる。
# ツイート情報取得用エンドポイントURL
request_status_url = "https://api.twitter.com/1.1/statuses/retweets/:id.json"
'''
情報を取得したいTweetIDをリストに格納
'''
tweet_id_list = ["XXXXX","XXXXX","XXXXX"] #リツイート情報を取得したい TweetID をここに差し込みます。
tweet_id_list.sort()
total_requests_number = len(tweet_id_list)
print("--------"+"送信するリクエスト数合計:" + str(total_requests_number)+"-------------")
'''
TwitterからUserID情報の取得開始
'''
sched_requests_number = 0 #リクエストしたtweet_idの数
should_get_requests_limit = True #API上限数を取得するためのスイッチ
i_plus = 1 #API上限数を取得するためのスイッチ
requests_count = 0 #「API上限までリクエストを送る」を実行するのは何回目かカウントする用
error_count = 0 #エラーを返された回数をカウントする用
output_csv_file_name = 'retweet_info.csv' #取得した値を格納ファイル名
'''
ループ開始前にカラムへ書き込み
'''
with open(output_csv_file_name,'a') as f:
    writer = csv.writer(f, lineterminator='\n')
    header = ['tweet_id', 'retweet_id', 'user_id', 'created_at']
    writer.writerow(header)
'''
ループ開始。retweet_idの書き込み。
'''
for i in range(0,total_requests_number,i_plus):
    if(should_get_requests_limit == True):
        api_response = request_authorization(request_url=request_status_url, ck=CK, cs=CS, at=AT, ats=AS)
        requests_limit = api_response.headers['x-rate-limit-remaining']#リクエスト可能残数の取得
        requests_limit = int(requests_limit)#limitが文字列なのでキャスト
        requests_count += 1
        print("--------"+str(requests_count)+"回目。今回送信するリクエスト数:" + str(requests_limit)+"--------------------")
        sched_requests_number += requests_limit
        should_get_requests_limit = False
    if(requests_limit != 0):
        i_plus = 1
        print(str(i) + ":リクエストしたtweetID:" + str(tweet_id_list[i])+"---------")
        request_url = "https://api.twitter.com/1.1/statuses/retweets/"+str(tweet_id_list[i])+".json?count=10&trim_user=false"
        params = {'tweet_id':tweet_id_list[i]}
        request_result = request_authorization(request_url=request_url, ck=CK, cs=CS, at=AT, ats=AS, params=params)
        if request_result.status_code == 200:
            tweetinfo = json.loads(request_result.text)#JSON形式で読み込む
            for j in range(0,len(tweetinfo)):
                    print(str(i)+":"+str(j)+":"+"リツイートID" + str(tweetinfo[j]['id']))
                    followerdata = {'tweet_id':tweet_id_list[i],
                                    'retweet_id':tweetinfo[j]['id'],
                                    'user_id':tweetinfo[j]['user']['id'],
                                    'created_at':tweetinfo[j]['created_at']}
                    with open(output_csv_file_name, 'a') as f:
                        writer = csv.writer(f, lineterminator='\n')
                        writer.writerow(followerdata.values())
        else:
            print ("Error: %d" % request_result.status_code)
            error_count += 1
            print("Error数:"+str(error_count))
    else:
        i_plus = 0 #limitが0のままiが1増えてしまうと実行されないTweeetIDが発生するので、0入れて増やさない。
    if(i == sched_requests_number):
        print("--------"+"残りリクエスト数" + str(total_requests_number-requests_limit) + "-------------")
        sleep_until_api_limit(api_response)
        should_get_requests_limit = True

情報を取得したいツイート ID と先ほど取得した key を上記のコードに差し込んで、以下のコマンドをターミナルで実行して終了です。

$ python3 get_retweet.py

実行後「 retweet_info.csv 」というファイルが作られます。注意して欲しいのですが、実行前に同名の csv ファイルを消しておきましょう。このコードはリクエストの度に「 retweet_info.csv 」に追記していく方式なので同名のファイルがあるとレコードが重複する可能性があります。以下はこのコードに到るまでの過程について記述します。

エンドポイント URL の調査

今回はツイート ID を送り、リツイートしたユーザにまつわる情報を取得したいので以下のエンドポイント URL を用いました。

  • https://api.twitter.com/1.1/statuses/retweets/:id.json

GET メソッドを用いるので上記の URL にツイート ID と取得したいリツートの数を追記してリクエストを投げます。
取得できるリツート情報は100件までという上限があります。

  • "https://api.twitter.com/1.1/statuses/retweets/"+str(tweet_id_list[i])+".json?count=100&trim_user=false"

自分が取得したい Twitter の情報によってエンドポイントも変化します。他の情報が欲しい場合には Twitter REST API の使い方の左メニューにある「リファレンス」を参考にします。エンドポイントの一覧が表示されています。何を送ったら何を返してくれるのか、一度に送れるリクエスト回数や返してくれる JSON のデータ構造、使い方等、エンドポイントにまつわる詳細が記述されています。

参考にしたコード

Python を使って Twitter のタイムラインを収集するという記事内にある簡潔で見やすいコードに、自分に必要だった機能をつけたしました。

from requests_oauthlib import  OAuth1Session
import json
import time
CK = 'XXXXXXXXXXXXXXXXXXXXXX'
CS = 'XXXXXXXXXXXXXXXXXXXXXX'
AT = 'XXXXXXXXXXXXXXXXXXXXXX'
AS = 'XXXXXXXXXXXXXXXXXXXXXX'
url = "https://api.twitter.com/1.1/statuses/home_timeline.json"
params = {'count': 100}
TweetList = []
twitter = OAuth1Session(CK, CS, AT, AS)
for i in range(100):
    req = twitter.get(url, params = params)
    if req.status_code == 200:
        timeline = json.loads(req.text)
        for tweet in timeline:
            TweetList.append(tweet["text"])
    else:
        print ("Error: %d" % req.status_code)
    time.sleep(240)

まとめ

API にリクエストを投げる基礎を学ぶことができました。必要なものを揃え、Twitter から目的の情報を取得する過程は非常に楽しかったです。コードは def を用いなかったため、非常に見づらいコードになってしまいました。今後は可読性に気をつけたいです。

GCP のメリットを最大限に活用しよう!

GCP・G Suite のご相談・
お見積り依頼はお気軽に
TEL.03-5840-8815
お問合せフォーム TEL.03-5840-8815