
twitter API
DataCampのIntermediate Importing Data in Pythonコースを学習しています。
ようやく最後のチャプター、③Diving deep into the Twitter APIです。Twitter APIからデータをストリーミングします。ストリーミングとはファイルをダウンロードしながら再生をすることのようです。
・Twitter APIからデータをストリーミングする方法
・入ってくるツイートをキーワードでフィルタリングする方法
・API認証とOAuthの原則
・Tweepyの使い方
Twitter APIにアクセスするには、まずはTwitter アカウントが必要。英語の質問が多くて初見だとめげます…。
DataCampの言う通りのコードを実行してみます。tweepyはインストールする必要がありました。
import tweepy, json
access_token="**********************************************"
access_token_secret="**********************************************"
consumer_key="**********************************************"
consumer_secret="**********************************************"
auth=tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
APIキーとシークレットをハンドラーに渡す。次に、set_access_tokenを使用して、アクセス資格情報に渡す。
class MyStreamListener(tweepy.StreamListener):
def __init__(self, api=None):
super(MyStreamListener, self).__init__()
self.num_tweets=0
self.file=open("tweets.txt", "w")
def on_status(self, status):
tweet=status._json
self.file.write(json.dumps(tweet)+'\\n')
tweet_list.append(status)
self.num_tweets+=1
if self.num_tweets<100:
return True
else:
return False
self.file.close()
Twitterストリームリスナークラスを定義する。tweets.txtというファイルを作成し、ストリーミングツイートを収集して書き込む。100のツイートがストリーミングされるとファイルを閉じてリスニングを停止する。
json.dump(変数)はPythonのデータ構造をJSONに変換して出力する。
l=MyStreamListener()
stream=tweepy.Stream(auth, l)
stream.filter(track=['apples', 'oranges'])
インスタンスを作成し、それを認証する。
次に、フィルターメソッドをオブジェクトストリームに適用することで、選択したキーワードを含むツイートをストリーミングできる。
実行してみると…
NameError: name 'tweet_list' is not defined
エラー。確かに、tweet_listは定義されていませんね…。
DataCampを彷徨うと、その後のExerciseでYou can find the code for the tweet stream listener class here.のリンクをクリックすると
class MyStreamListener(tweepy.StreamListener):
def __init__(self, api=None):
super(MyStreamListener, self).__init__()
self.num_tweets = 0
self.file = open("tweets.txt", "w")
def on_status(self, status):
tweet = status._json
self.file.write( json.dumps(tweet) + '\n' )
self.num_tweets += 1
if self.num_tweets < 100:
return True
else:
return False
self.file.close()
def on_error(self, status):
print(status)
修正されたwitterストリームリスナークラスがありました!!
これで動いた!でもめちゃくちゃ時間かかります。
止まったと思ったらエラーが表示されました。
ProtocolError: ('Connection broken: IncompleteRead(2 bytes read)', IncompleteRead(2 bytes read))
でもtweets.txtは作成されているのでOKとしましょう。
次はexerciseと少し変えて、python, JavaScript, Ruby, Swiftの単語でフィルターをかけてみます。C++入れたかったけど、エラーになったので除外しました…。
stream.filter(track=['python', 'JavaScript', 'Ruby','Swift'])
次にローカルに保存したtweets.txtをロードして、探検します。
import json
tweets_data_path='tweets.txt'
tweets_data=[]
tweets_file = open(tweets_data_path, "r")
for line in tweets_file:
tweet=json.loads(line)
tweets_data.append(tweet)
tweets_file.close()
print(tweets_data[0].keys())
<出力>
dict_keys(['created_at', 'id', 'id_str', 'text', 'source', 'truncated', 'in_reply_to_status_id', 'in_reply_to_status_id_str', 'in_reply_to_user_id', 'in_reply_to_user_id_str', 'in_reply_to_screen_name', 'user', 'geo', 'coordinates', 'place', 'contributors', 'quoted_status_id', 'quoted_status_id_str', 'quoted_status', 'quoted_status_permalink', 'is_quote_status', 'quote_count', 'reply_count', 'retweet_count', 'favorite_count', 'entities', 'favorited', 'retweeted', 'filter_level', 'lang', 'timestamp_ms'])
tweets.txtは1行が{"created_at" : "…" , "id": …, …}といった一つのツイートのデータ。これはJSONの形式なので、json.loads()
tweets_dataという空のリストを作成し、JSON形式のツイートを入れていきます。tweets_data[0]の型はdictです。
# Import package
import json
# String of path to file: tweets_data_path
tweets_data_path='tweets2.txt'
# Initialize empty list to store tweets: tweets_data
tweets_data=[]
with open(tweets_data_path, "r") as file:
text=file.read()
for line in text:
tweets_data.append(line)
print(tweets_data)
少し自分でも変えてみようと思い、JSONじゃなくてもいいのかな、とコードを試したら
あれ~?
twitter dataをDataFrameへ
tweets_dataをDataFrameにして、上位5つがどんなツイートか、どの言語かを出力します。
import pandas as pd
df = pd.DataFrame(tweets_data, columns=['text','lang'])
print(df.head())
ptはポルトガル語かな?undはundefinedみたいです。絵文字だけだから?
テキストを解析する
python, JavaScript, Ruby, Swiftを含むツイートがいくつあるか数えてみましょう。
まずはword_in_text()関数を定義します。第一引数(単語)が、第二引数(ツイート)内に存在するかどうかを教えてくれる。
import re
def word_in_text(word, text):
word = word.lower()
text = text.lower()
match = re.search(word, text)
if match:
return True
return False
正規表現モジュール re、先頭に限らずマッチするかチェック
python, javascript, ruby, swift = 0, 0, 0, 0
for index, row in df.iterrows():
python += word_in_text('python', row['text'])
javascript += word_in_text('JavaScript', row['text'])
ruby += word_in_text('Ruby', row['text'])
swift += word_in_text('Swift', row['text'])
df.iterrows()メソッドは、1行ずつそのインデックス名(行名)とそのデータのタプルを取得します。つまり、1ツイートずつ取得します。
グラフにしてみましょう。
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(color_codes=True)
cd = ['python', 'JavaScript', 'Ruby','Swift']
ax = sns.barplot(cd,[python, javascript,ruby, swift])
ax.set(ylabel="count")
plt.show()
他の言語に比べて、Swiftが圧倒的に多いですね。これはテイラースウィフトなども含んでいるからでは??