ツイートを200件以上取得する

python

TwitterAPIを用いてツイートを取得できるよういろいろと試行錯誤してきましたが、またさらに少し改良しました。

前回までに作ったもの

①1度に取得できる最大の200件のツイートをTwitter APIを使って取得し、csvとして保存できるようにしてみた

(記事はこちら↓)

Twitter APIでツイート取得してみた
Twitterアカウントを削除する予定だけど、その前にツイートをデータで保存しておいたりできないかな?ということでネットで検索してみたら、たくさんの人がやってました。ということで、私もいろいろな方のブログ記事などを参考に、Twit...

②タイムゾーンがUTC(イギリス)になっていたのをJST(日本)に変更した

(記事はこちら↓)

データのタイムゾーンを変更する
前回、TwitterAPIを用いてツイートを取得しました!が、タイムゾーンがイギリス時間(UTC)になっていました。なので、今回はタイムゾーンを日本時間(JST)に変更する方法を調べて実装してみました。前回のツイート取得に...

今回は200件以上取得することを目標にいろいろ調べてやってみたので記録しておきます。

目標

特定のアカウントのツイートを200件以上取得し、csvとして保存する。

やってみる

ぼんやり方針を考える

複数回APIを叩くのなら、繰り返し文が必要かな、というのはなんとなく考えてました。

2回目以降は直前に取得したツイートより1つ前のツイートから取得したいけれどどうすればよいのか・・・?

max_idというパラメータがあるらしい

調べると、パラメータとして「max_id」というのがあるようでした。

「max_id」で指定したIDを、取得してくるツイートの上限にすることができます。

なので、1回前に取得したツイートの中で一番小さいツイートIDから-1した数をmax_idに設定することで、続きからツイートを取得できるようになります。

    max_id = int(<前回取得してきた中で一番古いツイートのID>) - 1
    params["max_id"] = max_id

こんな感じで使ってmax_idを指定しました。

繰り返し処理

取得してくるツイートがなくなるまで、複数回APIを叩いて上限の200ツイートを取ってくるようにしたいので、繰り返し処理を書きました。

終了の条件は、200ツイート取得できたかどうかにしました。まだ続きがあればもう1回繰り返し、なければ終了。

#繰り返し処理
while True:
    res = twitter.get(url, params=params)

~取得したリストの処理(省略)~

#繰り返し終了の条件
if len(<取得したツイートのリスト>) < params['count'] :
                break

今書いてて気づきましたが、これでは全ツイート数が1回で取得するツイート数で割り切れるときにエラー吐きそうですね・・・。改善の余地あり・・。

まとめ コード全体

繰り返し処理とmax_idパラメータを駆使してなんとか複数回APIを叩く仕様にできました。

ただ、さかのぼれるツイート数の上限なのか期間の上限なのかわかりませんが、ツイートの量によっては全ツイート取得できず途中で止まっていることもあるような感じでした。

(私のツイートは400くらいしかなかったから全部とれますが・・!)

まだまだ改善の余地が大ありですが、いったんここで区切りとしたいと思います。

最後に今回作ったコードの全体を載せて記録しておきます。

中途半端な出来栄えではありますが、少しでもどなたかの参考になればうれしいです。

get_tweet.py ※別でアクセストークン等記載した.envファイルを作成

import os
import json
from requests_oauthlib import OAuth1Session
from dotenv import find_dotenv, load_dotenv
import pandas as pd
import datetime
from dateutil import tz

env_file = find_dotenv()
load_dotenv(env_file)  # .envファイルを探して読み込む

# APIキーの設定
CONSUMER_KEY = os.environ.get('CONSUMER_KEY')
CONSUMER_SECRET = os.environ.get('CONSUMER_SECRET')
ACCESS_KEY = os.environ.get('ACCESS_KEY')
ACCESS_KEY_SECRET = os.environ.get('ACCESS_KEY_SECRET')

twitter = OAuth1Session(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_KEY, ACCESS_KEY_SECRET)

#エンドポイント
url = 'https://api.twitter.com/1.1/statuses/user_timeline.json'

# パラメータ設定(count:ツイート投稿数、screen_name:アカウント名)
params = {'count':200, 'screen_name':<アカウント名>}


#tweetを取得(1回目)
res = twitter.get(url, params=params)

#ステータスコードが正常値(200)のときの処理
if res.status_code == 200:

    # json形式に変換
    timelines = json.loads(res.text)

    # 空のリスト型を作成
    list_created_at_utc = []
    list_created_at_jst = []
    list_text = []
    list_favorite_count = []

    #データを作成したリストに追加
    for data in timelines:
        list_created_at_utc.append(datetime.datetime.strptime(data['created_at'], '%a %b %d %H:%M:%S %z %Y'))
        list_text.append(data['text'])
        list_favorite_count.append(data['favorite_count'])

    #ここから2回目以降のツイート取得
    if len(timelines) == params['count'] :

        #パラメータにmax_idを追加
        max_id = int(timelines[params["count"] - 1]["id"]) - 1
        params["max_id"] = max_id

        #ここから繰り返し処理
        while True:
            res = twitter.get(url, params=params)

            timelines = json.loads(res.text)

            for data in timelines:
                list_created_at_utc.append(datetime.datetime.strptime(data['created_at'], '%a %b %d %H:%M:%S %z %Y'))
                list_text.append(data['text'])
                list_favorite_count.append(data['favorite_count'])


            #終了の条件
            if len(timelines) < params['count'] :
                break

            #max_idを更新
            max_id = int(timelines[params["count"] - 1]["id"]) - 1
            params["max_id"] = max_id


    #イギリス時間を日本時間に変換
    for utc in list_created_at_utc:
        list_created_at_jst.append(utc.astimezone(tz.gettz('Asia/Tokyo')))

    #DataFrame作成
    df = pd.DataFrame({'time': list_created_at_jst,
                        'text': list_text,
                        'fav_count': list_favorite_count
                        })

    #CSVに抽出
    df.to_csv("tweets_" + params['screen_name'] + ".csv")

else:
    print("ERROR: %d" % res.status_code)
タイトルとURLをコピーしました