Twitter API を使って特定ツイートをリツイートしたユーザーを取得する方法を調べた

特定のツイートをリツイートしたユーザー一覧を取得する必要があったので、その方法を調べました。
結論から言うと、事前準備をしなかった場合では、リツイートしたユーザーを完全に取得するのは難しいことがわかりました。

Twitter API を使ってリツイートを取得する方法

詳しくは [Twitter API] リツイートを100件より多く取得する方法 | プログラミング生放送 にまとまっています。

Retweets API を使う

Retweets API には特定ツイートをリツイートしたユーザーを取得するための 2 つのエンドポイントがあります。

GET statuses/retweets/:id は特定ツイートに対する最新のリツイートをユーザー情報付きで最大 100 件まで取得できます。
GET statuses/retweeters/ids も同じようなエンドポイントですが、リツイート自体ではなくリツイートしたユーザーの ID のみを最大 100 件まで取得できます。

これらの API は最大でも 100 件しか取得できない制限があります。 そのためリツイートしたユーザーを 100 人以上取得したい場合は、定期的に実行して結果を保存しておくなどする必要があります。

例として Node 環境で twitter モジュールを使ったときのソースコードを載せておきます。 GET statuses/retweets/:id からユーザー情報を取得して、CSV 形式で標準出力に出力します。

const Twitter = require('twitter');

const client = new Twitter({
  consumer_key: process.env.CONSUMER_KEY,
  consumer_secret: process.env.CONSUMER_SECRET,
  access_token_key: process.env.ACCESS_TOKEN,
  access_token_secret: process.env.ACCESS_TOKEN_SECRET
});

const params = {
  id: 'TARGET_TWEET_ID',
  count: 100
};

client.get('statuses/retweets', params, (err, tweets) => {
  if (err) {
    console.error(err);
    return;
  }

  console.log('id_str,created_at,user.id_str,user.name,user.screen_name');
  for (const status of tweets) {
    const columns = [
      status.id_str,
      status.created_at,
      status.user.id_str,
      status.user.name,
      status.user.screen_name
    ];
    console.log(columns.join(','));
  }
});

Standard Search API を使う

Standard Search API は 7 日以内のツイートを検索できるエンドポイントであり、これを利用して対象ツイートに含まれる文字列で検索を行うことで、リツイートを取得することができます。 Retweets API における 100 件の制限を超えてリツイートを取得することができますが、Standard Search API にも制限があり、検索対象となる期間は 7 日以内であり、更に 7 日以内であっても全てのツイートが検索対象となるわけではありません1

以下に twitter モジュールを使ったときのソースコード例を載せておきます。 同様にリツイートとそのユーザー情報を CSV 形式で標準出力に出力します。

const querystring = require('querystring');

const Twitter = require('twitter');

const client = new Twitter({
  consumer_key: process.env.CONSUMER_KEY,
  consumer_secret: process.env.CONSUMER_SECRET,
  access_token_key: process.env.ACCESS_TOKEN,
  access_token_secret: process.env.ACCESS_TOKEN_SECRET
});

(async () => {
  console.log('id_str,created_at,user.id_str,user.name,user.screen_name,text');

  const params = {
    q: 'TARGET_TWEET_TEXT',
    since_id: 'TARGET_TWEET_ID',
    count: 100
  };

  while (true) {
    const response = await client.get('search/tweets', params).catch(err => {
      console.error(err);
      process.exit(1);
    });

    for (const status of response.statuses) {
      const escapedText = status.text.replace(/\n+/g, '\\n');
      const columns = [
        status.id_str,
        status.created_at,
        status.user.id_str,
        status.user.name,
        status.user.screen_name,
        escapedText
      ];
      console.log(columns.join(','));
    }

    if (response.search_metadata.next_results) {
      const next_results = querystring.parse(
        response.search_metadata.next_results.replace(/^\?/, '')
      );
      params.max_id = next_results.max_id;
    } else {
      break;
    }
  }
})();

リクエストパラメータの q には対象ツイートに含まれるテキストなどを、since_id には対象ツイートの ID を設定します。 100 件以上取得するにはパラメータ max_id を設定して結果のページングを行う必要があり、設定すべき max_id の値は、直前のレスポンスの search_metadata.next_results プロパティにクエリ文字列として含まれているので、それをパースして設定しています。

q パラメータによっては思ったような結果が得られない場合もあり、何度か試行錯誤をしたり、結果のツイートのテキストを元にフィルタリングしたりする必要がありました。

番外編:メール通知を使う

注意:アイデアでしかなく、実現可能かどうかはわかりません。

自分のリツイートリツイートされたことをメールで通知されるように設定しておき、後から受信したメールを検索すればリツイートしたユーザーを取得できるのではないでしょうか?
試していないのと、メール通知にそれほど詳しくないので、実現可能かどうかはわかりません。

まとめ

Twitter API を使って特定ツイートをリツイートしたユーザーを取得する方法を調べました。 Retweets API では直近 100 件までのリツイートを、Standard Search API では直近 7 日間のおおよそのリツイートを取得できることがわかりました。

7 日間以上に渡ってリツイートを取得したい場合はこれらの API を定期的に実行するか、Premium Search API を利用する必要があると思われます。