どん底から這い上がるまでの記録

どん底から這い上がりたいけど這い上がれない人がいろいろ書くブログ(主にプログラミング)

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をつかうときは上のプログラムの続きに書いているものとします。

タイムラインの取得

自分のタイムラインと指定したユーザーのタイムラインの取得方法。(※一度に取得できるタイムラインの数は最大で20件までです。)

自分のタイムライン(※Developer登録で使用したアカウント)を取得するには以下のようにする。手に入れたタイムラインstatus_listはStatusオブジェクトが入ったリストになっている。

status_list = api.home_timeline()

 

指定したユーザーのタイムラインを取得するには@に続く、スクリーンネームを渡します。

status_list = api.user_timeline(screen_name="pytry3g")

どちらの方法でもstatus_listには最大で20のツイートが入っていて、これらのツイートの情報を見るには

from datetime import timedelta # 日本時間に直すために使う

for i, status in enumerate(status_list):
    print("- {} -".format(i+1))
    print("ツイートのID", status.id)
    print("ツイートした時間", status.created_at + timedelta(hours=+9))
    print("ツイート", status.text)
print("ユーザ名", status.user.name)
print("スクリーンネーム", status.user.screen_name)
print("フォロー数", status.user.friends_count)
print("フォロワー数", status.user.followers_count)
print("概要(自己紹介が書かれているやつ)", status.user.description)

ツイートの情報はStatusオブジェクト、ツイートをしたユーザの情報はStatusオブジェクトのuserから見ることができる。

ツイートの検索

ツイートの検索をするには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 自己紹介?