Twitter APIをpythonで使うと〇〇ができる。

 

Twitter APIの基本的な使い方を記事にしてまとめてみました。

この記事ではpythonTwitter APIのライブラリtweepyを使って、いろいろやっていきます。

 

 

関連リンク

Tweepy Documentation — tweepy 3.5.0 documentation

Tweet object — Twitter Developers

前準備

まずはtweepyをpipでインストール。pip install tweepy

Twitter APIを利用するにはAPI keyやAccess tokenが必要になるので、持ってない方はDeveloper登録の申請を始めにする必要があります。

Developer登録の方法は次の記事参照。

www.pytry3g.com

REST APIを使ってみる。

ここでは使用制限が厳しいREST APIの使い方について書いていきます。

まずはOAuth認証をしてAPIインスタンスを作ります。(認証キーは各自Developer登録をすると使えるようになります。)

import tweepy

# 認証キーの設定
consumer_key = "API key"
consumer_secret = "API secret key"
access_token = "Access token"
access_token_secret = "Access token secret"

# OAuth認証
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

# APIのインスタンスを生成
api = tweepy.API(auth)

# ここにやりたいこと書く(例:ツイートの検索、投稿等々)

以下、REST APIをつかうときは上のプログラムの続きに書いているものとします。

タイムラインの取得

自分のタイムラインと指定したユーザーのタイムラインの取得方法について書いた記事。基本的な使い方から一度に大量のツイートを取得する方法が書かれています。

www.pytry3g.com

ツイートの検索

ツイートの検索をするにはsearch()を使います。

status_list = api.search(q="検索ワード")

ツイートの投稿と指定したユーザーへのリプライ

ツイートを投稿するにはupdate_status()を使います。

api.update_status("Hello World!!!")

 

過去に投稿したツイートと全く同じものをツイートしたら以下のエラーが出ます。

    raise TweepError(error_msg, resp, api_code=api_error_code)
tweepy.error.TweepError: [{'code': 187, 'message': 'Status is a duplicate.'}]

 

リプライするには返信先のツイートのIDをin_reply_to_status_idに渡します。

例えば次のツイートに返信したい場合、status/以下の値がツイートのIDになります。

f:id:pytry3g:20190212144948p:plain

リプライするときは必ず返信先のスクリーンネームを入れましょう。

api.update_status(
    status="@aitry3g Me Too!!!",
    in_reply_to_status_id=1095191272719970304
)

 

例えば、あるユーザーの最新のツイートにリプライしたいときは次のようにします。

status = api.user_timeline(screen_name="pytry3g")[0]
api.update_status(
    status="@pytry3g So cool!!!",
    in_reply_to_status_id=status.id
)

リツイートする

retweet(id)リツイートできます。

下の例は特定のユーザの最新のツイートをリツイートしています。

status = api.user_timeline(screen_name="pytry3g")[0]
api.retweet(status.id)

自分or指定したユーザのフォロワーの情報を見る

フォロワーの情報を見るにはfollowers()を使います。何も渡さなければ自分のフォロワーを見ることができ、指定したユーザーのフォロワーを見るには次のようにします。

followers_list = api.followers(screen_name="pytry3g")
for follower in followers_list:
    # friends_count : フォロー数
    # followers_count : フォロワー数
    # description : 概要(自己紹介が書かれているやつ)
    print(follower.screen_name, follower.name, 
          follower.friends_count, follower.followers_count,
          follower.description)

一度に取得できるフォロワーの数は最大で100件までです。

フォローしたと見せかけて速攻フォロー解除する

フォローするにはcreate_friendship(screen_name)

# フォローする
api.create_friendship(screen_name="pytry3g")

 

フォロー解除するにはdestroy_friendship(screen_name)

# フォロー解除
api.destroy_friendship(screen_name="pytry3g")

あるユーザー同士がお互いにフォローし合っているか確認する

あるユーザー同士がお互いにフォローし合っているか確認するにはfriend_ship(source_screen_name, target_screen_name) を使います。

結果は長さが2のタプルの形になっていて、一つ目の要素にはユーザーAがユーザーBをフォローしているかをfollowingにTrueもしくはFalse、ユーザーAがユーザーBにフォローされているかがfollowed_byにTrueもしくはFalseが入っています。

二つ目の要素でユーザーBがユーザーAをフォローしているか、ユーザーBがユーザーAにフォローされているかを確認できます。

for friendship in api.show_friendship(source_screen_name="pytry3g", target_screen_name="aitry3g"):
    print(friendship.screen_name)
    print(friendship.following)
    print(friendship.followed_by)

 

トレンドを取得する

トレンドを取得するにはtrends_place(id)、idにはWOEIDを指定する。

これにより指定した地域のトレンドを取得できる。

WOEIDはこちらのサイトで検索でき、検索結果は入力フォームを下にスクロールすると見ることができます。

woeid = {
    "日本": 23424856,
    "札幌": 1118108, "仙台": 1118129, 
    "東京": 1118370, "京都": 15015372, "大阪": 15015370,
    "広島": 1117227, "福岡": 1117099, "沖縄": 2345896
}

for area, wid in woeid.items():
    print("--- {} ---".format(area))
    # リストになっているので取り出す
    trends = api.trends_place(wid)[0]
    #print(trends.keys()) # trends, as_of, created_at, locations
    #print(len(trends["trends"])) # 50
    for i, content in enumerate(trends["trends"]):
        print(i+1, content['name'])
    print("----------")

このコードでトレンド(※一度に50個)を取得できる。

Twitter APIを使うとこんなことができます。

①現在地球上(宇宙ステーションを含める)で投稿されているツイートを手に入れる

タイトルが少し大袈裟になってしまいましたが、Streaming APIを使うと現在世界で投稿されているツイートを手に入れることができます。

ただし、すべてのツイートを手に入れることはできません。

世界で投稿されているツイートの中からランダムに選ばれたものを手に入れることができます。

手順はざっとこんな感じです。

  1. TweepyのStreamListenerを継承する。
  2. 認証する。
  3. TweepyのStreamを作成する。

twitter_api.pystreaming_status.pyを使ってツイートを手に入れてみます。ソースコードは下に置いてあります。

 

1. TweepyのStreamListenerを継承する。

手に入れたツイートはStatusオブジェクトの形でon_status()に渡されます。

ツイートを見るには.textスクリーンネームを見るには.user.screen_nameです。詳細はこの記事の一番↓にあるツイートの属性についてに書きました。

class StreamingListener(tweepy.StreamListener):

    def on_status(self, status):
        print(status.text)

    def on_error(self, code):
        pass

 

2 and 3. 認証し、ストリームの作成。

if __name__ == "__main__":
    # 認証
    auth = twitter_api.get_authentication()
    api = tweepy.API(auth)
    # Streaming API
    listener = StreamingListener()
    streaming = tweepy.Stream(auth, listener)

 

リアルタイムで投稿されているツイートを手に入れる

1 ~ 3が完了すれば、準備は整いました。あとは、sample()もしくはfilter()を使うとこの世界で投稿されているツイートを手に入れることができます。

    while True:
        try:
            #streaming.filter(track=["python", "trump"], languages=["en"])
            streaming.sample()
        except KeyboardInterrupt:
            streaming.disconnect()
            break
        except Exception as e:
            streaming.disconnect()
            print(e)

sample()を使うと世界で投稿されているツイートの中からランダムに選ばれたものを手に入れることができます。オプションで言語やキーワードの指定はできないのでon_status()でツイートのフィルタリングをする必要があります。

フィルタリングのサンプル(クリックすると見れるかも)
#追加で必要ライブラリ
import re
from datetime import timedelta


    def on_status(self, status):
        # is_invalid_tweetでいらないツイートか調べる
        ### 取り除くツイート一覧 ###
        # 日本語ではないツイート
        # リプライ
        # スクリーンネームにbotを含むユーザーのツイート
        # URLを含むツイート
        # ハッシュタグを含むツイート
        # リプライではないがツイートにスクリーンネームを含むツイート
        if self.is_invalid_tweet(status):
            return
        print(status.created_at + timedelta(hours=+9), status.text)


    def is_invalid_tweet(self, status):
        # いらないツイートか調べる
        if status.user.lang != "ja":
            # 日本語か確認
            return True

        if isinstance(status.in_reply_to_status_id, int):
            # リプライならTrue
            return True
        
        if "bot" in status.user.screen_name:
            return True

        if re.search(r"https?://", status.text):
            return True

        if re.search(r"#(\w+)", status.text):
            # ハッシュタグ
            return True

        if re.search(r"@([A-Za-z0-9_]+)", status.text):
            return True

filter()を使うとオプションである単語を含むツイート、指定した言語のツイートのみを手に入れることができますが、個人的にこの方法はお勧めしません。

単語を指定するにはtrackを使いますが、複数の単語を指定したときに手に入れることができるツイートは指定した単語がひとつでも含まれていた場合のみです。

次の例だと、

例(track=["python", "trump"])

  • pythonを含むツイート or trumpを含むツイートを手に入れることができる

要するに単語を複数指定した場合、指定した単語全てを含むツイートは手に入れることは難しいです。pythonjavaを指定すると両方を含んだツイートを手に入れることができるかもしれませんが。

しかも、日本語のような単語の前後に空白が無い言語だとtrackにカレーを指定すると、

手に入れることができるツイート

川崎 ランチ》ランチ営業始めました!ドリンク&サラダ付きのランチメニュー500円~♪ #川崎 #ランチ #食べ放題 #カレー!!

手に入れることができないツイート

カレーおいすぃ

指定したキーワードがハッシュタグになっているもの、もしくは指定したキーワードの前後に空白があるツイートは手に入れることができます。

そのため、日本語のキーワードでフィルタリングしたい場合はsample()を使ってon_status()内で正規表現などでフィルタリングするのがいいと思います。

①のソースコード

twitter_api.py(クリックすると見れるかも)
import tweepy

# 自分の認証キー
consumer_key = "API key"
consumer_secret = "API secret key"
access_token = "Access token"
access_token_secret = "Access token secret"

def get_authentication():
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    return auth
streaming_status.py(クリックすると見れるかも)
import twitter_api
import tweepy


class StreamingListener(tweepy.StreamListener):

    def on_status(self, status):
        print(status.text)

    def on_error(self, code):
        pass


if __name__ == "__main__":
    # 認証
    auth = twitter_api.get_authentication()
    api = tweepy.API(auth)
    # Streaming API
    listener = StreamingListener()
    streaming = tweepy.Stream(auth, listener)
    while True:
        try:
            #streaming.filter(track=["python", "trump"], languages=["en"])
            streaming.sample()
        except KeyboardInterrupt:
            streaming.disconnect()
            break
        except Exception as e:
            streaming.disconnect()
            print(e)

会話データを手に入れる

seq2seq用のデータを集める方法について。

www.pytry3g.com

 

Twitter APIを利用して3つの発話から構成する対話データを収集してみた。

www.pytry3g.com

おまけ

スクリーンネームって何?

スクリーンネームは赤い矢印がさしているところ。

f:id:pytry3g:20190216145426p:plain

手に入れたツイートがリツイートかどうか調べる方法

ツイートがリツイートでなければ、retweeted_statusがツイートの属性には含まれないので、以下のようにすればツイートがリツイートか確認できる。

result = api.search(q="検索ワード")
# 検索結果をひとつずつ取り出す
for tweet in result:
    print(tweet.text) # ツイート
    # リツイートならTrue、そうでないならFalse
    print(hasattr(tweet, "retweeted_status")) 
    print("-"*30)

in演算子使ったほうが楽かな?

result = api.search(q="検索ワード")
# 検索結果をひとつずつ取り出す
for tweet in result:
    print(tweet.text)
    if "RT" in tweet.text:
        print(True)
    else:
        print(False)
    print("-"*30)

ツイートの中身の情報について

Statusオブジェクトの中身
status.text ツイート
status.id ツイート固有のID
status.in_reply_to_status_id リプライ先のツイートID
status.retweet_count リツイート
status.favorite_count いいねの数
status.user.name ユーザー名
status.user.screen_name スクリーンネーム(@pytry3g)
status.user.friends_count フォロー数
status.user.followers_count フォロワー数
status.user.description 自己紹介?