0
1

More than 1 year has passed since last update.

tweepyでRT直後のツイートを全件取得してCSVに出力

Posted at

はじめに

どうも,Heroku無料枠廃止のニュースに戦々兢々としているyagaodekawasuです。
友人と作ったTRPGの補助ツール「Shinobi-Mas」について友人がTwitterで宣伝したところ,思いの外拡散されました。

せっかく伸びたので,RT先でどのように言及されているか調べて今後の開発の参考にしようと思ったんですが,RTした人全員のTweetを手動で見に行くのは限界があると思い,tweepyを使ってTwitter APIを叩いて自動収集できるようにしました。

コードはGitHubにおいてあります。

注意

今回作成したスクリプトは,ある程度伸びが落ち着いた状態でTweetの全件取得を1回行うというものです。今まさに伸びているTweetの反響をリアルタイムで収集するためにはもっと色々工夫が必要になると思います。

また,無料で使えるTwitter APIでは7日以上前のTweetを取得することができません。その点もお気をつけください。

前提条件

今回のコードを動かすためには,以下の条件を満たす必要があります。

  1. Twitter DeveloperサイトでTwitterAPI用のAppを作成し、APIキーを取得
  2. アクセストークンキーとシークレットキーを取得
  3. Elevatedにレベルをあげる
  4. Pythonの実行環境を用意してpandas, pytz, tweepyをインストールする

1, 2のやりかたはこちら
【Twitter】APIキー利用申請から発行までの手順解説|ツイッター運用自動化アプリ作成に向けた環境構築

3のやりかたはこちら
【2022年度最新版】Twitter API 申請方法(Twitter v1.1 v2対応)

ポイント

APIクライアント作成

api = tweepy.API(auth, wait_on_rate_limit=True)

APIクライアント作成時に,オプションでwait_on_rate_limit=Trueを指定しています。

これはTwitter APIの実行回数制限(今回の検索APIは15分間に180回まで)を超えてしまった場合,異常終了せずに一定時間スリープして,再びAPIを叩けるようになったら処理を再開してくれるので,自分でエラーハンドリングを考える必要がなくなるという便利なやつです。

ターミナル上にも下のようにメッセージが出るので安心です。

Rate limit reached. Sleeping for: 860

RTのみを検索

ret = api.search_tweets(q="「Shinobi-Mas」を公開 filter:nativeretweets", count=100, max_id=max_id)

RT先で何を言われているか調べるには誰がRTしたか特定する必要があり,そのためにはRTの一覧が必要です。

幸い,Search APIのクエリには(引用を含まない純粋な)RTだけを取得するfilter:nativeretweetsというコマンドがあるので,それを使いましょう。

ループ処理

max_id = -1

while True:
    # 初回以外は,前回取得した最後のTweetのID - 1をmax_idとする
    if max_id != -1:
        max_id -= 1

    ret = api.search_tweets(q="「Shinobi-Mas」を公開 filter:nativeretweets", count=100, max_id=max_id)

    # 検索結果が0件になったら終了
    if len(ret) == 0:
        break

    for tweet in ret:
        # 何かしらの処理

    # max_idの更新
    max_id = ret[-1].id

これは下のサイトで紹介されているコードをtweepy用に書き換えたものになります。max_idを更新することによって,前のAPI呼び出しで取得した100件より古い次の100件を取得することができます。

TwitterAPIを用いたクローラー作成 | DATUM STUDIO株式会社

search_tweetsの戻り値はTweetオブジェクトのリスト(新→旧の順)になっているので,lenで検索結果の数を調べられるし,IDや本文などTweetの属性へのアクセスも簡単です。比べてみるとtweepyの便利さがわかりますね。

検索期間の設定

since = tweet.created_at.strftime("%Y-%m-%d_%H:%M:%S_UTC")
until = (tweet.created_at + timedelta(minutes=10)).strftime("%Y-%m-%d_%H:%M:%S_UTC")

RTしたユーザーがRT直後に何を呟いているか調べるために,検索期間を指定します。

大抵の場合,RTしたTweetについて言及するなら10分以内には呟くだろうという想定で,今回は「RTした時刻から10分」という範囲で指定します。

Tweetオブジェクトのcreated_at属性はdatetime型(UTC)になっているので,timedeltaで調整しつつstrftimestrに変換することができます。

検索クエリのsinceuntilはタイムゾーンを指定しなければ自動的にUTCと解釈されるとは思いますが,念のため末尾に_UTCを付けています。このへんはお好みで。

タイムスタンプの整形

#関数: UTCをJSTに変換する
def change_time_JST(u_time):
    #イギリスのtimezoneを設定するために再定義する
    utc_time = datetime(u_time.year, u_time.month,u_time.day, \
    u_time.hour,u_time.minute,u_time.second, tzinfo=timezone.utc)
    #タイムゾーンを日本時刻に変換
    jst_time_since = utc_time.astimezone(pytz.timezone("Asia/Tokyo"))
    # 文字列で返す
    str_time_since = jst_time_since.strftime("%Y-%m-%d_%H:%M:%S")
    return str_time_since

# 中略

            # Tweet日時(JST)
            ctime = change_time_JST(ret2[-1].created_at)

RT直後のTweetを取得してCSVに書き込む前に,Tweet作成時刻をJSTの見やすい形に整えます。

この関数は以下のサイトで紹介されているものを使用させていただきましたので,詳しい解説はそちらをご覧ください。

【コピペするだけ!】Pythonでツイート情報を取得する方法【初心者でも簡単】

CSVへの書き込み

# CSVに書き込む用のマスターDataFrame
df = pd.DataFrame({}, columns=['name', 'screen_name', 'text', 'created_at'])

while True:
    # 中略
        for tweet in ret:
            # 中略

            # 1行のDataFrameを作成してマスターに結合
            df2 = pd.DataFrame({'name': [user.name], 'screen_name': [user.screen_name], 'text': [text], 'created_at': [ctime]})
            df = pd.concat([df, df2])

# DataFrameをCSVに出力
df.to_csv('out.csv', index=False)

今回はpandasのDataFrameを生成し,それをCSVに出力するという方法でやってみました。

最初にマスターを作成して,そこに1行ずつ追加していくんですが,リストのようにappendでどんどん追加していくということがDataFrameではできず,別のDataFrameを作ってマスターにconcatで結合するという方式を採りました。

pandasに詳しくないので,これがベストなのかわかりません。もっといいやり方があったら教えてください。

実行結果

スクリプトを実行して出力されたCSVをExcelで読み込むとこんな感じになります(元Tweetに関係ある部分だけ表示してます)。
キャプチャ.JPG
約800RTに対して,出力はおよそ160行。そのうち元Tweetに関係ありそうなものは34件でした。だいたい4%ってところですかね。

好意的な意見が多くて一安心です。

まとめ

tweepyは便利です。

最後までご覧いただきありがとうございました。

参考

API — tweepy 4.10.1 documentation
Tweet object | Docs | Twitter Developer Platform
Twitterの検索で時間を含む期間指定をする方法 - Qiita
Twitter API(Tweepy) でのレート制限をハンドリングする方法|Tweepy Rate limit エラーで困ったら - Compass note
pandas.DataFrameに列や行を追加(assign, appendなど) | note.nkmk.me
pandasでDataFrameをcsvファイルに書き出す(to_csv):インデックスのありなしに注意しよう - Irohabook
[Twitter API] リツイートを100件より多く取得する方法 – プログラミング生放送

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1