TwitterのStreaming APIについて
2018年8月にTwitterのUser Streams APIが廃止されてしまい、タイムラインのツイートをリアルタイムで取得することができなくなってしまいました。 forest.watch.impress.co.jp
それに伴い、User Streams APIを使っていたリプライによるアイコン変更スクリプトなどが動かなくなっていました。
昨日から開発を始めた画像収集スクリプトを作るためにTweepyのドキュメントを眺めていたら、Streaming APIというものが現在も存在していることに気がついたのでこれを紹介します。
(2015年からTweepyに実装されていたのに今日まで気づかなかった……。ドキュメントはちゃんと読むべき。)
statuses/filter
の仕様
2020年4月15日現在、Twitter APIの紹介ページでタイトルにrealtimeとつくものにはFilter realtime TweetsとSample realtime Tweetsの2つがあります。このうち、無料ユーザーが使えるのはstatuses/filter
だけっぽいです。
このAPIを使うと特定の条件を満たすツイートをリアルタイムで取得できます。パラメータは5つあります。
follow
: ユーザーIDのリスト(上限5000個)track
: 検索キーワード(上限400個)locations
: ツイートされた場所(上限25個)delimited
: メッセージを長さで区切るかどうかstall_warnings
: stall warningsの有無
follow
, track
, locations
から複数を指定した場合、ORでつないだものとみなされます。
follow
で指定したユーザーについて、以下を満たすツイートが取得できます。(カッコ内は原文)
- 指定したユーザーによるツイート (Tweets created by the user.)
- 指定したユーザーがリツイートしたツイート (Tweets which are retweeted by the user.)
- 指定したユーザーの任意のツイートに対するリプライ (Replies to any Tweet created by the user.)
- 指定したユーザーの任意のツイートのリツイート (Retweets of any Tweet created by the user.)
- リプライボタンを押さずに行われた手動リプライ (Manual replies, created without pressing a reply button (e.g. “@twitterapi I agree”).)
しかし、以下のツイートは含まれません。
- 指定したユーザーにメンションしているツイート (Tweets mentioning the user (e.g. “Hello @twitterapi!”).)
- リツイートボタンを押さずに行われた手動リツイート (Manual Retweets created without pressing a Retweet button (e.g. “RT @twitterapi The API is great”).)
- 非公開アカウントによるツイート (Tweets by protected users.)
特に最後の「非公開アカウントによるツイート」の制約は厳しく、実験した限りではフォローしている鍵アカウントのツイートであっても取得することができません。
Tweepyでの使い方
Streaming With Tweepyを読んでください。
follow
に自分がフォローしているアカウントと自分を指定して、取得できたツイートに含まれる画像を保存するスクリプトの例を示します。
# -*- coding: utf_8 -*- import os import sys import urllib.request from urllib.parse import urlparse import tweepy class MyStreamListener(tweepy.StreamListener): def on_status(self, status): if 'media' in status.entities: for media in status.extended_entities['media']: media_url = media['media_url'] filename = os.path.basename(urlparse(media_url).path) if not os.path.exists(filename): try: urllib.request.urlretrieve(media_url, filename) print("Saved :", filename) except IOError: print("Failed to save the image from", media_url, file=sys.stderr) consumer_key = 'xxxxxxxxxxxxxxxxxxxxxxxxx' consumer_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' access_token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' access_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_token, access_secret) api = tweepy.API(auth) followee_ids = api.friends_ids(screen_name=api.me().screen_name) watch_list = [str(user_id) for user_id in followee_ids] watch_list.append(str(api.me().id)) # followには5000人までしか指定できない # https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter assert(len(watch_list) <= 5000) myStreamListener = MyStreamListener() myStream = tweepy.Stream(auth=api.auth, listener=myStreamListener) myStream.filter(follow=watch_list)