X APIを使い始めたのでそのメモ。
準備(Free前提)
アカウント作成。ちなみに誓約文みたいなの最初に書かされるが、僕は以下のように書いて提出した。
I plan to use the Twitter API to automate the posting and deletion of my own tweets. The frequency will be a few times per day at most. Additionally, I want to explore the capabilities of the Twitter API to evaluate potential business use cases. This includes testing API functionalities to understand their limitations and usability. The data accessed through the API will not be resold or used for commercial redistribution.
Freeプランなら、アカウント作成した時点でアプリがデフォルトでなんかできてる。デフォルトのやつを選択して、以下をGenerateする。
- API Key
- API Secret
- Access Token
- Access Token Secret
最初にできるのはReadだけ。
WriteにはOAuth2.0による認証認可が必要になる。
- Twitter Developer Portal (https://developer.twitter.com/en/portal/dashboard) にアクセス
- 作成したアプリを選択
- "Settings" > "User authentication settings" に移動
- App permissionsを編集し、"Read and Write" を選択
- 権限変更後、トークンを再生成
以後、Access TokenとAccess Token Secretを置き換えることで、Writeもできるようになる。
レート制限
レート制限がキツイので、最初に書いておく。
公式を参照しつつ。
- 15分が一つの単位
- Free Limitだと、ほとんどのWrite系リクエストは15分に1度しか許されない
- 負荷が重そうなものは1日単位
- 削除については、1日あたり17回までのようだ。17ってどっから出てきたんだろう……。
- トレンドやユーザ情報取得系に至っては1日に1回しかできない。とてもカジュアルに試せるものではない。
- トレンド系はBasic以上($200/月……)じゃないと使えない
- ユーザ検索などPro以上($5000/月……)じゃないと使えないものもある
例によってマスクがマスクであるために、現時点(2025-02-12)における情報でしかない。またすぐ変わりそうだが、緩和される可能性は低い。
基本的な使い方
プロフィール取得、投稿、削除。Free Limitは制限めっちゃ厳しいので、カジュアルに実行するとすぐ制限くらう。自分の情報取得は何度か使える。
import requests
from requests_oauthlib import OAuth1
API_KEY = "xxxx"
API_SECRET = "xxxx"
ACCESS_TOKEN = "xx-xx"
ACCESS_SECRET = "xxxx"
# OAuth 1.0a 認証
auth = OAuth1(API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_SECRET)
def get_user_info():
"""
自分のユーザー情報を取得する関数
"""
API_URL = "https://api.twitter.com/2/users/me"
response = requests.get(API_URL, auth=auth)
if response.status_code == 200:
print(response.json())
user_data = response.json().get("data", {})
print(f"ユーザー情報取得")
print(f"ID: {user_data.get('id')}")
print(f"名前: {user_data.get('name')}")
print(f"ユーザー名: {user_data.get('username')}")
return user_data
else:
print(f"エラー発生: {response.status_code}")
print(response.json())
return None
def post_tweet(text):
"""
指定したテキストでツイートを投稿する関数
"""
API_URL = "https://api.twitter.com/2/tweets"
payload = {"text": text}
response = requests.post(API_URL, json=payload, auth=auth)
if response.status_code == 201:
tweet_id = response.json().get("data", {}).get("id")
print(f"ツイート成功 ID: {tweet_id}")
return tweet_id
else:
print(f"エラー発生: {response.status_code}")
print(response.json())
return None
def delete_tweet(tweet_id):
"""
指定したIDのツイートを削除する関数
"""
API_URL = f"https://api.twitter.com/2/tweets/{tweet_id}"
response = requests.delete(API_URL, auth=auth)
if response.status_code == 200:
print(f"ツイート削除成功 ID: {tweet_id}")
return True
else:
print(f"エラー発生: {response.status_code}")
print(response.json())
return False
# 関数を使用する例
user_info = get_user_info()
# tweet_id = post_tweet("テストツイート")
# delete_tweet(tweet_id)
usernameからユーザの情報を取得する
Free Limitでも15分に3回使えて比較的緩い。
ここからは認証認可をOAuth 2.0でやる。Bearer Tokenをデベロッパーポータルから取得し、それを使ってアクセスする。
import requests
# Bearer Token認証を使用
BEARER_TOKEN = "xxxx"
def get_user_by_username(username):
"""
指定したユーザー名のユーザー情報を取得
username: @を除いたユーザー名
"""
API_URL = f"https://api.twitter.com/2/users/by/username/{username}"
headers = {
"Authorization": f"Bearer {BEARER_TOKEN}"
}
params = {
'user.fields': 'description,created_at,profile_image_url,public_metrics'
}
response = requests.get(API_URL, headers=headers, params=params)
if response.status_code == 200:
return response.json()
else:
print(f"⚠️ エラー発生: {response.status_code}")
print(response.json())
return None
# 特定ユーザーの情報を取得
user = get_user_by_username("tamasan774")
print(user)結果
{
"data":{
"name":"tama",
"id":"3302753743",
"profile_image_url":"https://pbs.twimg.com/profile_images/1428753262660833284/zUwv5vPL_normal.png",
"description":"技術者の響きだけで生きてる。酒が飲みたい。",
"username":"tamasan774",
"public_metrics":{
"followers_count":154,
"following_count":93,
"tweet_count":24154,
"listed_count":8,
"like_count":17991,
"media_count":222
},
"created_at":"2015-07-31T19:15:51.000Z"
}
}指定した条件でツイートのカウント
基本的に無課金おじさんお断りだが、/GET /2/tweets/counts/recentだけはFreeプランでも使える。
import requests
# Bearer Token認証を使用
BEARER_TOKEN = "xxxx"
def get_recent_tweet_counts(query, start_time=None, end_time=None):
"""
過去7日間の特定クエリに一致するツイート数を時系列で取得
params:
- query: 検索クエリ(例: "#Python")
- start_time: 集計開始時間(ISO 8601形式)
- end_time: 集計終了時間(ISO 8601形式)
"""
API_URL = "https://api.twitter.com/2/tweets/counts/recent"
headers = {
"Authorization": f"Bearer {BEARER_TOKEN}"
}
params = {
'query': query,
'granularity': 'hour' # hour, day, minuteから選択可能
}
if start_time:
params['start_time'] = start_time
if end_time:
params['end_time'] = end_time
response = requests.get(API_URL, headers=headers, params=params)
if response.status_code == 200:
return response.json()
else:
print(f"エラー発生: {response.status_code}")
print(response.json())
return None
counts = get_recent_tweet_counts("ほげほげ")
print(counts)
結果
{
"data":[
{
"end":"2025-02-05T02:00:00.000Z",
"start":"2025-02-05T01:53:04.000Z",
"tweet_count":135
},
{
"end":"2025-02-05T03:00:00.000Z",
"start":"2025-02-05T02:00:00.000Z",
"tweet_count":1289
},
{
"end":"2025-02-05T04:00:00.000Z",
"start":"2025-02-05T03:00:00.000Z",
"tweet_count":1775
},
{
"end":"2025-02-05T05:00:00.000Z",
"start":"2025-02-05T04:00:00.000Z",
"tweet_count":1487
},
{
"end":"2025-02-05T06:00:00.000Z",
"start":"2025-02-05T05:00:00.000Z",
"tweet_count":1599
},
{
"end":"2025-02-05T07:00:00.000Z",
"start":"2025-02-05T06:00:00.000Z",
"tweet_count":1469
},
{
"end":"2025-02-05T08:00:00.000Z",
"start":"2025-02-05T07:00:00.000Z",
"tweet_count":1613
},
{
"end":"2025-02-05T09:00:00.000Z",
"start":"2025-02-05T08:00:00.000Z",
"tweet_count":1620
},
{
"end":"2025-02-05T10:00:00.000Z",
"start":"2025-02-05T09:00:00.000Z",
"tweet_count":1964
},
{
"end":"2025-02-05T11:00:00.000Z",
"start":"2025-02-05T10:00:00.000Z",
"tweet_count":1923
},
{
"end":"2025-02-05T12:00:00.000Z",
"start":"2025-02-05T11:00:00.000Z",
"tweet_count":1864
},
{
"end":"2025-02-05T13:00:00.000Z",
"start":"2025-02-05T12:00:00.000Z",
"tweet_count":1938
},
{
"end":"2025-02-05T14:00:00.000Z",
"start":"2025-02-05T13:00:00.000Z",
"tweet_count":1923
},
{
"end":"2025-02-05T15:00:00.000Z",
"start":"2025-02-05T14:00:00.000Z",
"tweet_count":1768
},
{
"end":"2025-02-05T16:00:00.000Z",
"start":"2025-02-05T15:00:00.000Z",
"tweet_count":1334
},
{
"end":"2025-02-05T17:00:00.000Z",
"start":"2025-02-05T16:00:00.000Z",
"tweet_count":962
},
{
"end":"2025-02-05T18:00:00.000Z",
"start":"2025-02-05T17:00:00.000Z",
"tweet_count":555
},
{
"end":"2025-02-05T19:00:00.000Z",
"start":"2025-02-05T18:00:00.000Z",
"tweet_count":440
},
{
"end":"2025-02-05T20:00:00.000Z",
"start":"2025-02-05T19:00:00.000Z",
"tweet_count":462
},
{
"end":"2025-02-05T21:00:00.000Z",
"start":"2025-02-05T20:00:00.000Z",
"tweet_count":735
},
{
"end":"2025-02-05T22:00:00.000Z",
"start":"2025-02-05T21:00:00.000Z",
"tweet_count":1271
},
{
"end":"2025-02-05T23:00:00.000Z",
"start":"2025-02-05T22:00:00.000Z",
"tweet_count":1902
},
{
"end":"2025-02-06T00:00:00.000Z",
"start":"2025-02-05T23:00:00.000Z",
"tweet_count":1858
},
{
"end":"2025-02-06T01:00:00.000Z",
"start":"2025-02-06T00:00:00.000Z",
"tweet_count":1623
},
{
"end":"2025-02-06T02:00:00.000Z",
"start":"2025-02-06T01:00:00.000Z",
"tweet_count":1415
},
{
"end":"2025-02-06T03:00:00.000Z",
"start":"2025-02-06T02:00:00.000Z",
"tweet_count":1286
},
{
"end":"2025-02-06T04:00:00.000Z",
"start":"2025-02-06T03:00:00.000Z",
"tweet_count":1682
},
{
"end":"2025-02-06T05:00:00.000Z",
"start":"2025-02-06T04:00:00.000Z",
"tweet_count":1108
},
{
"end":"2025-02-06T06:00:00.000Z",
"start":"2025-02-06T05:00:00.000Z",
"tweet_count":1046
},
{
"end":"2025-02-06T07:00:00.000Z",
"start":"2025-02-06T06:00:00.000Z",
"tweet_count":1029
},
{
"end":"2025-02-06T08:00:00.000Z",
"start":"2025-02-06T07:00:00.000Z",
"tweet_count":1096
},
{
"end":"2025-02-06T09:00:00.000Z",
"start":"2025-02-06T08:00:00.000Z",
"tweet_count":1058
},
{
"end":"2025-02-06T10:00:00.000Z",
"start":"2025-02-06T09:00:00.000Z",
"tweet_count":1128
},
{
"end":"2025-02-06T11:00:00.000Z",
"start":"2025-02-06T10:00:00.000Z",
"tweet_count":1145
},
{
"end":"2025-02-06T12:00:00.000Z",
"start":"2025-02-06T11:00:00.000Z",
"tweet_count":1286
},
{
"end":"2025-02-06T13:00:00.000Z",
"start":"2025-02-06T12:00:00.000Z",
"tweet_count":1282
},
{
"end":"2025-02-06T14:00:00.000Z",
"start":"2025-02-06T13:00:00.000Z",
"tweet_count":1103
},
{
"end":"2025-02-06T15:00:00.000Z",
"start":"2025-02-06T14:00:00.000Z",
"tweet_count":974
},
{
"end":"2025-02-06T16:00:00.000Z",
"start":"2025-02-06T15:00:00.000Z",
"tweet_count":863
},
{
"end":"2025-02-06T17:00:00.000Z",
"start":"2025-02-06T16:00:00.000Z",
"tweet_count":551
},
{
"end":"2025-02-06T18:00:00.000Z",
"start":"2025-02-06T17:00:00.000Z",
"tweet_count":332
},
{
"end":"2025-02-06T19:00:00.000Z",
"start":"2025-02-06T18:00:00.000Z",
"tweet_count":294
},
{
"end":"2025-02-06T20:00:00.000Z",
"start":"2025-02-06T19:00:00.000Z",
"tweet_count":288
},
{
"end":"2025-02-06T21:00:00.000Z",
"start":"2025-02-06T20:00:00.000Z",
"tweet_count":439
},
{
"end":"2025-02-06T22:00:00.000Z",
"start":"2025-02-06T21:00:00.000Z",
"tweet_count":682
},
{
"end":"2025-02-06T23:00:00.000Z",
"start":"2025-02-06T22:00:00.000Z",
"tweet_count":1159
},
{
"end":"2025-02-07T00:00:00.000Z",
"start":"2025-02-06T23:00:00.000Z",
"tweet_count":1232
},
{
"end":"2025-02-07T01:00:00.000Z",
"start":"2025-02-07T00:00:00.000Z",
"tweet_count":971
},
{
"end":"2025-02-07T02:00:00.000Z",
"start":"2025-02-07T01:00:00.000Z",
"tweet_count":860
},
{
"end":"2025-02-07T03:00:00.000Z",
"start":"2025-02-07T02:00:00.000Z",
"tweet_count":964
},
{
"end":"2025-02-07T04:00:00.000Z",
"start":"2025-02-07T03:00:00.000Z",
"tweet_count":1237
},
{
"end":"2025-02-07T05:00:00.000Z",
"start":"2025-02-07T04:00:00.000Z",
"tweet_count":826
},
{
"end":"2025-02-07T06:00:00.000Z",
"start":"2025-02-07T05:00:00.000Z",
"tweet_count":791
},
{
"end":"2025-02-07T07:00:00.000Z",
"start":"2025-02-07T06:00:00.000Z",
"tweet_count":766
},
{
"end":"2025-02-07T08:00:00.000Z",
"start":"2025-02-07T07:00:00.000Z",
"tweet_count":654
},
{
"end":"2025-02-07T09:00:00.000Z",
"start":"2025-02-07T08:00:00.000Z",
"tweet_count":661
},
{
"end":"2025-02-07T10:00:00.000Z",
"start":"2025-02-07T09:00:00.000Z",
"tweet_count":692
},
{
"end":"2025-02-07T11:00:00.000Z",
"start":"2025-02-07T10:00:00.000Z",
"tweet_count":773
},
{
"end":"2025-02-07T12:00:00.000Z",
"start":"2025-02-07T11:00:00.000Z",
"tweet_count":1072
},
{
"end":"2025-02-07T13:00:00.000Z",
"start":"2025-02-07T12:00:00.000Z",
"tweet_count":1054
},
{
"end":"2025-02-07T14:00:00.000Z",
"start":"2025-02-07T13:00:00.000Z",
"tweet_count":1021
},
{
"end":"2025-02-07T15:00:00.000Z",
"start":"2025-02-07T14:00:00.000Z",
"tweet_count":917
},
{
"end":"2025-02-07T16:00:00.000Z",
"start":"2025-02-07T15:00:00.000Z",
"tweet_count":573
},
{
"end":"2025-02-07T17:00:00.000Z",
"start":"2025-02-07T16:00:00.000Z",
"tweet_count":386
},
{
"end":"2025-02-07T18:00:00.000Z",
"start":"2025-02-07T17:00:00.000Z",
"tweet_count":310
},
{
"end":"2025-02-07T19:00:00.000Z",
"start":"2025-02-07T18:00:00.000Z",
"tweet_count":217
},
{
"end":"2025-02-07T20:00:00.000Z",
"start":"2025-02-07T19:00:00.000Z",
"tweet_count":179
},
{
"end":"2025-02-07T21:00:00.000Z",
"start":"2025-02-07T20:00:00.000Z",
"tweet_count":227
},
{
"end":"2025-02-07T22:00:00.000Z",
"start":"2025-02-07T21:00:00.000Z",
"tweet_count":348
},
{
"end":"2025-02-07T23:00:00.000Z",
"start":"2025-02-07T22:00:00.000Z",
"tweet_count":486
},
{
"end":"2025-02-08T00:00:00.000Z",
"start":"2025-02-07T23:00:00.000Z",
"tweet_count":632
},
{
"end":"2025-02-08T01:00:00.000Z",
"start":"2025-02-08T00:00:00.000Z",
"tweet_count":683
},
{
"end":"2025-02-08T02:00:00.000Z",
"start":"2025-02-08T01:00:00.000Z",
"tweet_count":581
},
{
"end":"2025-02-08T03:00:00.000Z",
"start":"2025-02-08T02:00:00.000Z",
"tweet_count":671
},
{
"end":"2025-02-08T04:00:00.000Z",
"start":"2025-02-08T03:00:00.000Z",
"tweet_count":741
},
{
"end":"2025-02-08T05:00:00.000Z",
"start":"2025-02-08T04:00:00.000Z",
"tweet_count":703
},
{
"end":"2025-02-08T06:00:00.000Z",
"start":"2025-02-08T05:00:00.000Z",
"tweet_count":556
},
{
"end":"2025-02-08T07:00:00.000Z",
"start":"2025-02-08T06:00:00.000Z",
"tweet_count":581
},
{
"end":"2025-02-08T08:00:00.000Z",
"start":"2025-02-08T07:00:00.000Z",
"tweet_count":769
},
{
"end":"2025-02-08T09:00:00.000Z",
"start":"2025-02-08T08:00:00.000Z",
"tweet_count":863
},
{
"end":"2025-02-08T10:00:00.000Z",
"start":"2025-02-08T09:00:00.000Z",
"tweet_count":742
},
{
"end":"2025-02-08T11:00:00.000Z",
"start":"2025-02-08T10:00:00.000Z",
"tweet_count":746
},
{
"end":"2025-02-08T12:00:00.000Z",
"start":"2025-02-08T11:00:00.000Z",
"tweet_count":782
},
{
"end":"2025-02-08T13:00:00.000Z",
"start":"2025-02-08T12:00:00.000Z",
"tweet_count":882
},
{
"end":"2025-02-08T14:00:00.000Z",
"start":"2025-02-08T13:00:00.000Z",
"tweet_count":702
},
{
"end":"2025-02-08T15:00:00.000Z",
"start":"2025-02-08T14:00:00.000Z",
"tweet_count":536
},
{
"end":"2025-02-08T16:00:00.000Z",
"start":"2025-02-08T15:00:00.000Z",
"tweet_count":306
},
{
"end":"2025-02-08T17:00:00.000Z",
"start":"2025-02-08T16:00:00.000Z",
"tweet_count":234
},
{
"end":"2025-02-08T18:00:00.000Z",
"start":"2025-02-08T17:00:00.000Z",
"tweet_count":170
},
{
"end":"2025-02-08T19:00:00.000Z",
"start":"2025-02-08T18:00:00.000Z",
"tweet_count":149
},
{
"end":"2025-02-08T20:00:00.000Z",
"start":"2025-02-08T19:00:00.000Z",
"tweet_count":129
},
{
"end":"2025-02-08T21:00:00.000Z",
"start":"2025-02-08T20:00:00.000Z",
"tweet_count":133
},
{
"end":"2025-02-08T22:00:00.000Z",
"start":"2025-02-08T21:00:00.000Z",
"tweet_count":202
},
{
"end":"2025-02-08T23:00:00.000Z",
"start":"2025-02-08T22:00:00.000Z",
"tweet_count":288
},
{
"end":"2025-02-09T00:00:00.000Z",
"start":"2025-02-08T23:00:00.000Z",
"tweet_count":400
},
{
"end":"2025-02-09T01:00:00.000Z",
"start":"2025-02-09T00:00:00.000Z",
"tweet_count":389
},
{
"end":"2025-02-09T02:00:00.000Z",
"start":"2025-02-09T01:00:00.000Z",
"tweet_count":391
},
{
"end":"2025-02-09T03:00:00.000Z",
"start":"2025-02-09T02:00:00.000Z",
"tweet_count":367
},
{
"end":"2025-02-09T04:00:00.000Z",
"start":"2025-02-09T03:00:00.000Z",
"tweet_count":377
},
{
"end":"2025-02-09T05:00:00.000Z",
"start":"2025-02-09T04:00:00.000Z",
"tweet_count":306
},
{
"end":"2025-02-09T06:00:00.000Z",
"start":"2025-02-09T05:00:00.000Z",
"tweet_count":356
},
{
"end":"2025-02-09T07:00:00.000Z",
"start":"2025-02-09T06:00:00.000Z",
"tweet_count":386
},
{
"end":"2025-02-09T08:00:00.000Z",
"start":"2025-02-09T07:00:00.000Z",
"tweet_count":394
},
{
"end":"2025-02-09T09:00:00.000Z",
"start":"2025-02-09T08:00:00.000Z",
"tweet_count":441
},
{
"end":"2025-02-09T10:00:00.000Z",
"start":"2025-02-09T09:00:00.000Z",
"tweet_count":557
},
{
"end":"2025-02-09T11:00:00.000Z",
"start":"2025-02-09T10:00:00.000Z",
"tweet_count":680
},
{
"end":"2025-02-09T12:00:00.000Z",
"start":"2025-02-09T11:00:00.000Z",
"tweet_count":574
},
{
"end":"2025-02-09T13:00:00.000Z",
"start":"2025-02-09T12:00:00.000Z",
"tweet_count":491
},
{
"end":"2025-02-09T14:00:00.000Z",
"start":"2025-02-09T13:00:00.000Z",
"tweet_count":425
},
{
"end":"2025-02-09T15:00:00.000Z",
"start":"2025-02-09T14:00:00.000Z",
"tweet_count":622
},
{
"end":"2025-02-09T16:00:00.000Z",
"start":"2025-02-09T15:00:00.000Z",
"tweet_count":479
},
{
"end":"2025-02-09T17:00:00.000Z",
"start":"2025-02-09T16:00:00.000Z",
"tweet_count":271
},
{
"end":"2025-02-09T18:00:00.000Z",
"start":"2025-02-09T17:00:00.000Z",
"tweet_count":156
},
{
"end":"2025-02-09T19:00:00.000Z",
"start":"2025-02-09T18:00:00.000Z",
"tweet_count":78
},
{
"end":"2025-02-09T20:00:00.000Z",
"start":"2025-02-09T19:00:00.000Z",
"tweet_count":91
},
{
"end":"2025-02-09T21:00:00.000Z",
"start":"2025-02-09T20:00:00.000Z",
"tweet_count":162
},
{
"end":"2025-02-09T22:00:00.000Z",
"start":"2025-02-09T21:00:00.000Z",
"tweet_count":259
},
{
"end":"2025-02-09T23:00:00.000Z",
"start":"2025-02-09T22:00:00.000Z",
"tweet_count":380
},
{
"end":"2025-02-10T00:00:00.000Z",
"start":"2025-02-09T23:00:00.000Z",
"tweet_count":457
},
{
"end":"2025-02-10T01:00:00.000Z",
"start":"2025-02-10T00:00:00.000Z",
"tweet_count":520
},
{
"end":"2025-02-10T02:00:00.000Z",
"start":"2025-02-10T01:00:00.000Z",
"tweet_count":504
},
{
"end":"2025-02-10T03:00:00.000Z",
"start":"2025-02-10T02:00:00.000Z",
"tweet_count":508
},
{
"end":"2025-02-10T04:00:00.000Z",
"start":"2025-02-10T03:00:00.000Z",
"tweet_count":616
},
{
"end":"2025-02-10T05:00:00.000Z",
"start":"2025-02-10T04:00:00.000Z",
"tweet_count":420
},
{
"end":"2025-02-10T06:00:00.000Z",
"start":"2025-02-10T05:00:00.000Z",
"tweet_count":421
},
{
"end":"2025-02-10T07:00:00.000Z",
"start":"2025-02-10T06:00:00.000Z",
"tweet_count":407
},
{
"end":"2025-02-10T08:00:00.000Z",
"start":"2025-02-10T07:00:00.000Z",
"tweet_count":437
},
{
"end":"2025-02-10T09:00:00.000Z",
"start":"2025-02-10T08:00:00.000Z",
"tweet_count":724
},
{
"end":"2025-02-10T10:00:00.000Z",
"start":"2025-02-10T09:00:00.000Z",
"tweet_count":1152
},
{
"end":"2025-02-10T11:00:00.000Z",
"start":"2025-02-10T10:00:00.000Z",
"tweet_count":1525
},
{
"end":"2025-02-10T12:00:00.000Z",
"start":"2025-02-10T11:00:00.000Z",
"tweet_count":1474
},
{
"end":"2025-02-10T13:00:00.000Z",
"start":"2025-02-10T12:00:00.000Z",
"tweet_count":1636
},
{
"end":"2025-02-10T14:00:00.000Z",
"start":"2025-02-10T13:00:00.000Z",
"tweet_count":1460
},
{
"end":"2025-02-10T15:00:00.000Z",
"start":"2025-02-10T14:00:00.000Z",
"tweet_count":1157
},
{
"end":"2025-02-10T16:00:00.000Z",
"start":"2025-02-10T15:00:00.000Z",
"tweet_count":765
},
{
"end":"2025-02-10T17:00:00.000Z",
"start":"2025-02-10T16:00:00.000Z",
"tweet_count":530
},
{
"end":"2025-02-10T18:00:00.000Z",
"start":"2025-02-10T17:00:00.000Z",
"tweet_count":429
},
{
"end":"2025-02-10T19:00:00.000Z",
"start":"2025-02-10T18:00:00.000Z",
"tweet_count":344
},
{
"end":"2025-02-10T20:00:00.000Z",
"start":"2025-02-10T19:00:00.000Z",
"tweet_count":298
},
{
"end":"2025-02-10T21:00:00.000Z",
"start":"2025-02-10T20:00:00.000Z",
"tweet_count":415
},
{
"end":"2025-02-10T22:00:00.000Z",
"start":"2025-02-10T21:00:00.000Z",
"tweet_count":654
},
{
"end":"2025-02-10T23:00:00.000Z",
"start":"2025-02-10T22:00:00.000Z",
"tweet_count":965
},
{
"end":"2025-02-11T00:00:00.000Z",
"start":"2025-02-10T23:00:00.000Z",
"tweet_count":1048
},
{
"end":"2025-02-11T01:00:00.000Z",
"start":"2025-02-11T00:00:00.000Z",
"tweet_count":1275
},
{
"end":"2025-02-11T02:00:00.000Z",
"start":"2025-02-11T01:00:00.000Z",
"tweet_count":1100
},
{
"end":"2025-02-11T03:00:00.000Z",
"start":"2025-02-11T02:00:00.000Z",
"tweet_count":1105
},
{
"end":"2025-02-11T04:00:00.000Z",
"start":"2025-02-11T03:00:00.000Z",
"tweet_count":1168
},
{
"end":"2025-02-11T05:00:00.000Z",
"start":"2025-02-11T04:00:00.000Z",
"tweet_count":1165
},
{
"end":"2025-02-11T06:00:00.000Z",
"start":"2025-02-11T05:00:00.000Z",
"tweet_count":1243
},
{
"end":"2025-02-11T07:00:00.000Z",
"start":"2025-02-11T06:00:00.000Z",
"tweet_count":1260
},
{
"end":"2025-02-11T08:00:00.000Z",
"start":"2025-02-11T07:00:00.000Z",
"tweet_count":1230
},
{
"end":"2025-02-11T09:00:00.000Z",
"start":"2025-02-11T08:00:00.000Z",
"tweet_count":1436
},
{
"end":"2025-02-11T10:00:00.000Z",
"start":"2025-02-11T09:00:00.000Z",
"tweet_count":1387
},
{
"end":"2025-02-11T11:00:00.000Z",
"start":"2025-02-11T10:00:00.000Z",
"tweet_count":1572
},
{
"end":"2025-02-11T12:00:00.000Z",
"start":"2025-02-11T11:00:00.000Z",
"tweet_count":1283
},
{
"end":"2025-02-11T13:00:00.000Z",
"start":"2025-02-11T12:00:00.000Z",
"tweet_count":1303
},
{
"end":"2025-02-11T14:00:00.000Z",
"start":"2025-02-11T13:00:00.000Z",
"tweet_count":1188
},
{
"end":"2025-02-11T15:00:00.000Z",
"start":"2025-02-11T14:00:00.000Z",
"tweet_count":1151
},
{
"end":"2025-02-11T16:00:00.000Z",
"start":"2025-02-11T15:00:00.000Z",
"tweet_count":819
},
{
"end":"2025-02-11T17:00:00.000Z",
"start":"2025-02-11T16:00:00.000Z",
"tweet_count":486
},
{
"end":"2025-02-11T18:00:00.000Z",
"start":"2025-02-11T17:00:00.000Z",
"tweet_count":292
},
{
"end":"2025-02-11T19:00:00.000Z",
"start":"2025-02-11T18:00:00.000Z",
"tweet_count":231
},
{
"end":"2025-02-11T20:00:00.000Z",
"start":"2025-02-11T19:00:00.000Z",
"tweet_count":224
},
{
"end":"2025-02-11T21:00:00.000Z",
"start":"2025-02-11T20:00:00.000Z",
"tweet_count":322
},
{
"end":"2025-02-11T22:00:00.000Z",
"start":"2025-02-11T21:00:00.000Z",
"tweet_count":536
},
{
"end":"2025-02-11T23:00:00.000Z",
"start":"2025-02-11T22:00:00.000Z",
"tweet_count":689
},
{
"end":"2025-02-12T00:00:00.000Z",
"start":"2025-02-11T23:00:00.000Z",
"tweet_count":736
},
{
"end":"2025-02-12T01:00:00.000Z",
"start":"2025-02-12T00:00:00.000Z",
"tweet_count":699
},
{
"end":"2025-02-12T01:53:04.000Z",
"start":"2025-02-12T01:00:00.000Z",
"tweet_count":664
}
],
"meta":{
"total_tweet_count":137215
}
}指定した条件でサーチする
多分だいたいみんなこれをやりたいんじゃないかと思うんだが、GET /2/tweets/search/recentつまり7日間でよければFreeプランでも使える。しかも15分に1回。今なら一応。それ以外はプロ以外お断りだ。
個人でも関心が高い話題についての情報収集くらいには使えるかも?流行言葉は制約的に厳しいと思うけど。
import requests
# Bearer Token認証を使用
BEARER_TOKEN = "xxxx"
def search_recent_tweets(query, max_results=10):
"""
過去7日間のツイートを検索
params:
- query: 検索クエリ
- max_results: 取得する最大ツイート数(10-100)
"""
API_URL = "https://api.twitter.com/2/tweets/search/recent"
headers = {
"Authorization": f"Bearer {BEARER_TOKEN}"
}
params = {
'query': query,
'max_results': max_results,
'tweet.fields': 'created_at,author_id,public_metrics'
}
response = requests.get(API_URL, headers=headers, params=params)
return response.json()
tweets = search_recent_tweets("手取りを増やす")
print(tweets)
# そのほかの使用例
# 画像付きの「猫」ツイートを検索
#tweets = search_recent_tweets("猫 has:images -is:retweet")
# 「Python」を含む日本語ツイート
#tweets = search_recent_tweets("Python lang:ja")
# 特定ユーザーの返信を除外したツイート
#tweets = search_recent_tweets("from:username -is:reply")
結果
{
"data":[
{
"public_metrics":{
"retweet_count":11,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"2929390645",
"edit_history_tweet_ids":[
"1889497408155095532"
],
"created_at":"2025-02-12T02:11:01.000Z",
"id":"1889497408155095532",
"text":"RT @oef4raF1ZW3D4WI: 国民民主「国民の手取りを増やす」\n維新「高校無償化」\n\n自民「企業に補助金。今まで以上に」\n\n少なくとも自民は無いわな。国民に益なし\n\nだいたい過去数十年失敗し続けてるのに、同じことをまだやろうってんだから反省も自浄作用もないわけだ。自…"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"999818589673668608",
"edit_history_tweet_ids":[
"1889496996140163153"
],
"created_at":"2025-02-12T02:09:23.000Z",
"id":"1889496996140163153",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"129119756",
"edit_history_tweet_ids":[
"1889496791734943868"
],
"created_at":"2025-02-12T02:08:34.000Z",
"id":"1889496791734943868",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":32,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"855312372818264064",
"edit_history_tweet_ids":[
"1889496781559656931"
],
"created_at":"2025-02-12T02:08:32.000Z",
"id":"1889496781559656931",
"text":"RT @shinjukuacc: 国民民主党が羨ましい?\n他の政党も「手取りを増やす」を掲げて選挙を戦えば良いだけの話では?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"1516766731095580677",
"edit_history_tweet_ids":[
"1889496743823433959"
],
"created_at":"2025-02-12T02:08:23.000Z",
"id":"1889496743823433959",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"808024200",
"edit_history_tweet_ids":[
"1889496377258025115"
],
"created_at":"2025-02-12T02:06:56.000Z",
"id":"1889496377258025115",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"1709033536626593792",
"edit_history_tweet_ids":[
"1889496311738802543"
],
"created_at":"2025-02-12T02:06:40.000Z",
"id":"1889496311738802543",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"265293455",
"edit_history_tweet_ids":[
"1889496046285496570"
],
"created_at":"2025-02-12T02:05:37.000Z",
"id":"1889496046285496570",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"1307860410",
"edit_history_tweet_ids":[
"1889496035309048008"
],
"created_at":"2025-02-12T02:05:34.000Z",
"id":"1889496035309048008",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
},
{
"public_metrics":{
"retweet_count":682,
"reply_count":0,
"like_count":0,
"quote_count":0,
"bookmark_count":0,
"impression_count":0
},
"author_id":"1140189324614361088",
"edit_history_tweet_ids":[
"1889495481585377443"
],
"created_at":"2025-02-12T02:03:22.000Z",
"id":"1889495481585377443",
"text":"RT @kirishima_O3: 国民民主党って「手取りを増やす」が公約なんだよね?\nだったら103万の壁にこだわるより、社会保険料増税に反対することの方が優先度高いんじゃないの?"
}
],
"meta":{
"newest_id":"1889497408155095532",
"oldest_id":"1889495481585377443",
"result_count":10,
"next_token":"b26v89c19zqg8o3frr9u7r3w21gbm3z1eldrda7d2ug71"
}
}
コメント