StatsBeginner: 初学者の統計学習ノート

統計学およびR、Pythonでのプログラミングの勉強の過程をメモっていくノート。たまにMacの話題。

Tweepyを使って、PythonでTwitterのAPIを超簡単に操作する

PythonでTwitterのAPIを触りたい

 PythonでTwitterのAPIを操作し、検索の自動化による情報収集・解析とか、自動でつぶやくbotの作成を可能にしたい。
 そこでTweepyというライブラリを使うと、とても簡単に態勢が整いました。10行以内のコードで準備が終わります。
 Tweepy


 ちなみにTwitterのAPIは「REST API」と「Streaming API」の2種類があって、今回使うのはREST APIのほうです。REST APIは(RESTというものの説明はREST - Wikipediaでもみてください)、HTTPリクエストを投げるとそれに対応した情報がjsonで送られてくるってやつで、特定のツイートやユーザの情報を取得したり、検索をしたり、つぶやいたりするのに使うものです。Streaming APIはTwitter上に流れる情報がリアルタイムに流れ込んでくるもので、ビッグデータ的な何かをやる特殊な人たち向けのもののようです(解説はこの記事とかこのスライド)。

  
 Tweepyの使い方の解説サイトはたくさんあり、私はたとえば
 PythonでTwitterAPIを使う。その2 - WhereToStart
 とかを参考にコードを書き始めました。しかし上記ページのコードでは一部動かないところもあったし、後述のとおりACCESS TOKENの取得は自動化せず直接記述してもいいので、Tweepyの公式サイトなども合わせて見ながらコードは改変していった。結果的にはほぼ公式サイトに載っている内容に落ち着きました。


 以下に導入手順をメモしてますが、今回はMac(Yosemite)のターミナルから操作してます。Pythonのバージョンは2.7.10です。

各種認証・認可キーの取得

 事前準備として、Twitterの公式サイトでアプリ開発者としての登録を行って、各種キーを取得しておく必要がある。
 これは以前、RからTwitterAPIをいじるためのtwitterRを試した時のエントリの「Twitterアプリ作成の登録を行う」という項に書いてある。
 RでTwitterのデータを分析するための準備(2015年6月現在のやり方) - StatsBeginner: 初学者の統計学習ノート
 
 
 簡単におさらいしておくと、

  1. まずツイッターアカウントに電話番号を紐づける。(このページから)
  2. 開発者用ページにいって新たなアプリを作成し、名前とかを付ける。(このページから)
  3. Keys and Access Tokensタブで、「Consumer Key」「Consumer Secret」を確認し控える。
  4. 下の方の「Token Actions」のところの「Create my access token」を押して、出てくる「Access Token」「Access Token Secret」を確認し控える。

 
 
 後述しますが、4のところは自分のTwitterアカウントで開発者になると同時に自分のアカウントへの操作権限を付与してもらおうとしているため、ここでボタン押すだけでアクセストークンがもらえるわけですが、このアプリを色々な人(色々なアカウントの保有者)が利用するという場合、その人ごとにTwitterに対して自分のアカウント用のAccess Tokenを要求するという手続きになります。


 ここで、なんたらキーとかが色々でてきてややこしいんですが、この辺のページを読むと何となく分かる気がします。OAuthの理解のために、読んでおいて損はないと思う。
 OAuthの鍵がたくさん登場するが各々の役割についてまとめてみた - 知のレバレッジを最大化せよ
 暇なメモ帳: OAuthとは何か?


 Consumerというのは要するにアプリのことであり、Consumer Key及びConsumer Secretは、「そのアプリの開発者として持っておく鍵」。
 Access TokenとSecretは、「そのアプリで操作したいTwitterアカウントの保有者として持つ鍵」であり、これを持っているとそのアカウントに自由にアクセスして操作することが可能になる。
 今回自分で作成しているアプリから自分のTwitterアカウントを操作する分には、開発者ページにおいてこの両方を一気にもらうことができるということです。
 他の人がこのアプリの利用者(User)として自分のTwitterアカウントに対しAccess Tokenを求める場合で言うと、

  1. Userが認証要求するたび毎にTwitterがRequest Tokenを発行してアプリに返してくれる。
  2. アプリはこれを用いたHTTPリクエストの手段をUserに提供する(例えばリンクを生成する等)。
  3. このリンク等によってUserが、Request Tokenを引っさげた状態でTwitterのサイトにアクセスし、「自分のアカウントにアクセスするためのAccess Tokenをくれ」と要求する。
  4. するとTwitterは、Access Tokenを要求しているUserに対して、要求先アカウントのID・PW入力を求める。IDが「どのアカウントを操作したいのか」を示し,PWが「そのアカウントの所有者である証拠」を示すわけ。
  5. PWが正しければ確認用のコード(Verifierと呼ばれる)が画面上で与えられるのでそれを控え、このコードをアプリに入力する。
  6. アプリがこのコードとRequest TokenをセットでTwitterに投げ、Twitterからそのアカウント用のAccess Tokenを受け取る。
  7. これにより、「あるアプリ」から「あるアカウント」にアクセスする権限が認められたことになる。
  8. Access Tokenはアプリが保管しており、UserがそのアプリからAPIを通じて自分のアカウントを操作する際はいつも、アプリ固有のConsumer Key及びConsumer Secretと、自分のアカウントから発行されているAccess Token及びAccess Token Secretという4つのキーを持って、アクセスを要求することになる。


 (・・・というような概略で理解したんだけど正確かどうかは怪しいので間違ってたらご指摘ください。)

TweepyのインストールとAPI操作の準備

 さて次にTweepyのインストールですが、これはとても簡単。
 easy_installでやる場合は、Macのターミナルから、

$ sudo easy_install tweepy
Password:


 これで終了。easy_installではなく「pip install tweepy」でもよい。各自のパッケージ管理ツールの使い方次第*1
 そして、次のようなコードを書いたスクリプト(テキストファイルに記述して拡張子を.pyにしたもの)を用意して保存しておく。一番上の行は環境によって違うかも。
 もちろん、スクリプトを用意せず対話環境下で一行ずつ打ち込んでも大丈夫。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Tweepyライブラリをインポート
import tweepy

# 各種キーをセット
CONSUMER_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXX'
CONSUMER_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
ACCESS_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

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

# これだけで、Twitter APIをPythonから操作するための準備は完了。
print('Done!')


 XXXXX...のところは、自分でTwitter開発者ページから取得したキーを入れます。
 ここでやってることは、

  1. "CONSUMER KEY"と"CONSUMER SECRET"をセットして、OAuthHandlerクラスのインスタンスを作成する。authというオブジェクトがそれ。
  2. OAuthHandlerインスタンス(auth)に、"ACCESS TOKEN"と"ACCESS TOKEN SECRET"をセットする。
  3. セットが終わったOAuthHandlerインスタンスから、TweepyのAPIクラスのインスタンスを作成する。apiというオブジェクトがそれ。


という流れ。
 私はこのスクリプトの名前を"twpy.py"としたので、Pythonの対話環境下で該当のディレクトリに行き*2

import twpy.py


 と書いてこれを呼び出します。すると"twpy.api"という名前のAPIクラスのインスタンスが作成されるので、あとはこのtwpy.apiにいろんなメソッドを適用することで、Twitter APIを操作することができます。*3


 なお、以下では"twpy.api"と打つのがめんどくさかったので、

api = twpy.api


 としてから「api」というオブジェクトを操作するようにしてるのですが、大きな意味はありません。

参考:ACCESS TOKENの入手の仕方

 先ほどのコードでは、4つのキーを開発者ページから事前に取得して上記の通り直接スクリプトの中に記述しましたが、OAuthの認証・認可手順としては、アプリのCONSUMER KEYからスタートして、認証用コードの入力などの手続きを挟んで操作したいアカウントにひも付け、ACCESS TOKENを取得するほうが普通の流れではあります。
 アプリ登録を行った開発用アカウントとは別のアカウントも操作したい場合は、そのようにしておいて切り替えられるようになってたほうがいいです。
 
 
 これは冒頭の解説ページを参考にしましたが、スクリプト内に以下のように書いといたらできた。
 上記コードの「ACCESS_TOKEN = ...」と「ACCESS_SECRET = ...」の行を消して以下のコードに置き換えれば、スクリプトを実行した際、ターミナル上にAccess Token要求用のURLが出力されるので、それをコピペしてブラウザに入力。Twitterアカウントへのログインが求められるのでID・PWを入力し、確認用コード(Verifier)が表示されたらそれを控えてターミナルに戻って入力すると、裏でAccess Tokenを取得してセットが行われます。

# 以下は、アクセストークンをもらいにいく場合のコード。
# まず、認証コードを貰いに行くアドレスを取得する
redirect_url = auth.get_authorization_url()

# アドレスを表示し、ブラウザでアクセスして認証用コードを取得してくる。
# べつにGetなんたらはなくてもよく、redirect_urlをprintするだけでもよい。
print 'Get your verification code from: ' + redirect_url

# ブラウザから取得してきた認証用コードを対話モードで入力する。
# strip()はコピペの際に末尾に改行コードとかスペースが入ったのを消すため。
verifier = raw_input('Type the verification code: ').strip()


# Access TokenとAccess Token Secretを取得してそれぞれオブジェクト
# として格納しておく。
auth.get_access_token(verifier)
ACCESS_TOKEN = auth.access_token
ACCESS_SECRET = auth.access_token_secret

 
 

Tweepyを使ってみる

 これで準備完了でTweepyが使えるようになったわけですが、具体的に何ができるようになったかというと、
 API Reference — tweepy 3.3.0 documentation
 このTweepy公式のReferenceに書かれているように、自分のTwitterアカウントに対する各種操作をPythonから実行できるようになったということです。
 できることは色々あるので、ここではためしに実行してみた簡単な例だけ載せておきます。
 ターミナル上での出力結果も書いているので、「>>> 」等の記号も含めてコピペしたものを掲載してます。


 たとえば現在の自分のタイムライン上の最新のツイートを参照するには、

>>> print api.home_timeline()[0].text
RT @estzet: 【宣伝】「美味兎屋」 玄関のドアをさらりと潜れば、漸く近づくその空間。 望み望まぬ明るい闇へ。 ゼロ割のごとき空間へ。 立方体の地平面。 常識ルールの無意味な世界。 ようこそ、みなさん、美味兎屋へ。 https://t.co/DUaMqNSdTM #na…


 と書けばよい。[0]はリストで返ってきている結果の1個目ということ。
 この書き方だとつぶやきの内容だけが表示されるんですが、これは末尾で.textという属性を指定しているからです。
 たとえば、

>>> api.home_timeline()[0]
Status(contributors=None, truncated=False, text=u'RT @syufutosousaku: \u3010\u5ba3\u4f1d\u3011\n\u54c0\u308c\u306a\u308b\u304b\u306a\u3001\u771f\u5b9f\u3092\u898b\u629c\u3051\u306c\u8005\u3088\u3002\u5831\u308f\u308c\u308b\u3053\u3068\u306e\u7121\u304d\u9ab8\u3088\u3002\n\u3010\u306e\u3056\u3089\u3057\u3011\nhttps://t.co/tKKyY6ZAxq\n\u9ad1\u9acf\u304c\u3057\u3083\u3079\u3063\u305f\u308a\u3001\u6b7b\u4f53\u304c\u52d5\u3044\u305f\u308a\u3059\u308b\u63cf\u5199\u304c\u304a\u5acc\u3044\u306a\u65b9\u306f\u3054\u6ce8\u610f\u3092\u3002', is_quote_status=False, in_reply_to_status_id=None, id=656681903483781120, favorite_count=0, _api=<tweepy.api.API object at 0x102eaedd0>, source=u'Tabtter Free', _json={u'contributors': None, u'truncated': False, ...途中省略...)


 と打ってみるとわかるように、もともとは1つのツイートに対してめちゃめちゃ長い情報が存在しています。上記はコピペは途中から省略していて、実際にはこの場合、1件のツイートに対して半角34,000字分ぐらいの情報が返ってきてました……。
 さっきはこの、1件のツイートに付与されている大量の情報の中の、textという属性だけを呼び出したということになります。
 属性の指定によって、ふぁぼの有無とか、リプライならその宛先はどこかとか、ツイートの位置情報とかを、個別に取得することもできます。
 
 
 次に、自分のアカウントでつぶやくには、たとえば、

>>> api.update_status(status='オッス! from Tweepy')  


 と書けば良い。


 f:id:midnightseminar:20151021132250p:plain


 このへんを応用すれば、botがつくれるわけですね。TwitterのAPIではつぶやきをstatusと呼んでいるようです。ちなみにフォローは「create_friendship」で,アンフォローは「destroy_friendship」(笑)と言うみたい。


 ツイートを検索する場合は、たとえば「安倍」を検索ワードとすると、

>>> search_result = api.search(q='安倍')


 と書けばいい。このsearch_resultに.textというメソッドを適用すると、ヒットしたツイートの文面が出力される。
 デフォルト設定だと15件結果が格納されているので、forで順番に出力してみます。

>>> search_result = api.search(q='安倍')
>>> for result in search_result:
...     print result.text
... 
RT @hivere: 仲良しの安倍自民党も同じく、党是は「国民の生存権弾圧」@naniwacchiやっぱり大阪維新の会の党是は「生存権弾圧」なんだよ。「
 @12koku
経済が失速すればするほど、経済経済と叫ぶ安倍政権が支持される。誰が失速させたが問われないのが現状。楽して儲かる軍需産業へ傾斜するのもわかる。先は地獄でも進まなくてはならないと言われて勇ましいと思う人が一定数いるのは事実。「敗戦後、次は勝つぞと、願う馬鹿。」
RT @gogoichiro: 異例というより、この国の政治史において初でしょう。つい先日まで、共産党は安倍自民党は子供達を戦場に送る、戦争法案を命がけで廃案にすると言ってたのに、大阪では安倍自民党より維新を潰さなければならないと自共共闘となる。 https://t.co/XS…
RT @tokyoseijibu: 第3次安倍改造内閣で新設された一億総活躍担当相は一体何をするのか政権内からも困惑の声が上がっています。https://t.co/NMWWqwEiz1
RT @alres9: @21remon @Aahi69Mai 安倍さんに媚びないんじゃなくて、権威に媚びてないんですけど、違いが分からないようです(笑)
RT @kitanihonganba: 「諸君とともに、先頭に立って全力を尽くす」〜観艦式で安倍総理が訓示http://t.co/xAlcTjvXrU

諸君の後ろには、常に諸君を信頼し、諸君を頼りにする日本国民がいます
私と日本国民は、全国25万人の自衛隊と共にある http…
https://t.co/l16D9Uftq3 宮根、辛坊、そして1位はやっぱりあの人…安倍政権と安保法制を後押しした“戦争協力者”ランキング5位〜1位
RT @kei_nakazawa: 10月24日(土)18時30分から。東京堂で中野晃一さんとお話します。ヘイトスピーチを軸に見た安倍政権についたて。詳細とお申込みはこちら → https://t.co/T0CdoKRsWQ
#society #jounalistic
 安倍政権に代わる枠組みを/TBSラジオ小池氏が主張 野党結束が大事/民主・維新の各議員と議論 - しんぶん赤旗:
 日本共産党の小池晃副委員長は19日、TBSラジオの.. https://t.co/WbCTxCzwPs
RT @ROCKERS_channel: 日本で人気の4人グループ「T.O.K.」解散へ。安倍首相の訪ジャマイカ晩餐会出席後すぐ。 https://t.co/JJJ6Zu0sJT

結成から23年。実は8年前からメンバー内の人間関係に問題を抱えていたんだ……。 https://…
【日本も乗り遅れるな!】カナダ総選挙で野党自由党が圧勝!TPPには慎重姿勢!世界中で止まらない反安倍的な流れ!  https://t.co/t2DazXjIow
RT @renho_sha: 怒りを覚える。
24年度補正で1591725年度補正で12231億
安倍内閣が基金に支出した税金。その大半が年度内に使われす、埋蔵金化、バラマキに使われているものもある中、子どもの貧困対策は民間支出の基金?政府が予算確保すべきだ
https:/…
RT @SatoMasahisa: 【これはひどい、「安倍政権批判の文言入り文具、有無を調査 北海道の学校 」
教育現場に「アベ政治を許さない」文字のクリアケース、北海道教育委員会は政治的中立性上問題、一方教職員組合側は教育現場を萎縮させると反発。組合側の常識を疑う
http:…
誤った政策が招いた好ましくない結果を他人のせいにする無責任さには今更ながら呆れるばかりだ。経済政策ブレーンの浜田宏一(イェール大学教授)なども無責任さでは安倍にヒケを取らない。
政治家や政策立案者などが無責任なのは、国民が無責任だから?
次回の国政選挙で、そうでないことを示そう。
RT @ishincheck: 考えが合わない人同士がいる部屋にゴキブリが出てきたら、
その時ばかりは協力して退治しますよね。
そういう事です。
@gogoichiro 大阪では安倍自民党より維新を潰さなければならないと自共共闘となる。


 物騒なツイートがたくさん返ってきました。


 とりあえず動かせるようになったので、これから色々試してみます。
 ここから先はとにかく、
 API Reference — tweepy 3.3.0 documentation
 このReferenceをみながら、やりたいことを探して操作してみればいいですね。必要に応じてTwitterのAPIの仕様も参照しながら(ツイートを取得する件数を指定するときのページ数みたいな概念がまだよくわかってなかったりする)。


 基本的には、行いたい操作に対応するメソッドをひたすら「api」に適用していくだけ、つまり「api」のあとに「.なんたら()」を付けて、カッコの中に引数を入れていくだけでTwitterへのリクエストが発射できるので、難しいことはあまりないと思います。
 レスポンスとして返ってくるデータ(JSONで返ってきているらしい)から必要な情報を指定して抜き出すことさえできれば、あとはそれを形態素解析するなり単語の頻度を集計するなりRT回数を調べるなり、好きにすればいいということです。
 

 たとえば特定のツイートの内容を取得するのであれば、get_statusというメソッドを適用し、引数にIDを入れればよく、返ってくるデータのうちどの属性を表示したいかをまた「.属性名」と書いて指定する。
 こんな感じで。

>>> print api.get_status(656974416312598528).text  # ツイート本文を表示
スプラトゥーンはやばい。廃人になってしまうので博論提出までは控えるようにしてる。
>>> print api.get_status(656974416312598528).retweet_count  # RT件数を表示
1
>>> 


 返ってくるデータの読み方は後日まとめました。

www.statsbeginner.net

*1:パッケージ管理ツールについてはここを参照 http://www.yunabe.jp/docs/python_package_management.html

*2:Python起動前に移動しててもいいし、Pythonの対話環境ではosモジュールをインポートしてos.chdir('パスを記述')とすればよい。

*3:もちろん、スクリプトにどんな名前をつけ、どこに保存し、どうやって呼び出すかとかは、各々の判断で行うもの。対話環境で呼び出しているのも単に今回試してみる上で私がそうしているだけであり、別のスクリプトから呼び出してもよい。