TwitterAPIを使ってみるテスト3(TwitterAPI Version1.1)

前回のエントリで、ライブラリTweepyを使ってTwitterAPIを使ってみました。
TwitterAPIを使ってみるテスト2(OAuth) « Walk on apps.

ただ、TweepyではAPI Version1.0にアクセスしているようでした。今年の3月に、Version1.0は使えなくなります。
そのため今回は、TweepyでAPI Version1.1を使ってみるテスト、をやってみることにします。

使っている環境:
Python2.5.4
Tweepy 1.12
Windows7(64bit)


2/20追記
14日頃にTweepyが、アップデートされたようです。
Version2では、「Twitter API 1.1 support.」とのことなので、こちらをお勧めします。


(1)TwitterAPIの仕様確認

とりあえずTwitterAPI Version1.0と1.1の違いを確認します。
例として、Twitterトレンド情報取得のURIを見てみます。マニュアルはこちら。
GET trends/:woeid | Twitter Developers
GET trends/place | Twitter Developers

日本のトレンドを取得する場合、
v1.0では、http://api.twitter.com/1/trends/23424856.json
v1.1では、https://api.twitter.com/1.1/trends/place.json?id=23424856
となる。

バージョン名と、「trends/*****」のところが変わります。


(2)ライブラリTweepyのどこをなおせばいいか

まずは、URIに含まれるバージョン名の部分について。
ライブラリTweepyの中に、api.pyというファイルがあり、この中を見てみると、class APIの中で初期値「api_root=’/1’」が設定されていました。

class API(object):
    """Twitter API"""

    def __init__(self, auth_handler=None,
            host='api.twitter.com', search_host='search.twitter.com',
             cache=None, secure=False, api_root='/1', search_root='',
            retry_count=0, retry_delay=0, retry_errors=None,
            parser=None):

そのため、アプリ作成時にTweepyを使うときにapi_root=’/1.1′ を指定することにします。以下のような形でコーディングすることになります。

        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth)
            ↓     ↓
        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth_handler=auth, api_root='/1.1')

次に「trends/*****」の修正について。
さっきとおなじapi.pyファイルを見てみると、

    """ trends/location """
    trends_location = bind_api(
        path = '/trends/{woeid}.json',
        payload_type = 'json',
        allowed_param = ['woeid']
    )

となっているため、この書き方にならって、api.pyファイルのAPIクラスに、メソッドを追加してみます。(メソッド名をapi1_1_trends_placeにしてみました。)

# API1.1
    """ trends/place """
    api1_1_trends_place = bind_api(
        path = '/trends/place.json',
        payload_type = 'json',
        allowed_param = ['id']
    )

これで、Tweepyを使うときにapi.api1_1_trends_place(id=’23424856′)として呼び出せば、トレンド情報を取得できるようになります。コーディングのイメージは以下のような形になります。

        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth_handler=auth, api_root='/1.1')

        # trend情報取得
        trends_available=api.api1_1_trends_available()
        trends_place=api.api1_1_trends_place(id='23424856')

(3)最終的なコーディングまとめ

ライブラリTweepyの、api.pyファイルに、メソッド3つ追記しました
次の3つの機能について追記しています。
・トレンド情報でのWoeid一覧取得
・トレンド情報取得
・ツイートする

追記内容は以下になります。

# API1.1
    """ trends/available """
    api1_1_trends_available = bind_api(
        path = '/trends/available.json',
        payload_type = 'json',
        allowed_param = ['lat', 'long']
    )

# API1.1
    """ trends/place """
    api1_1_trends_place = bind_api(
        path = '/trends/place.json',
        payload_type = 'json',
        allowed_param = ['id']
    )

# API1.1
    """ statuses/update """
    api1_1_statuses_update = bind_api(
        path = '/statuses/update.json',
        method = 'POST',
        payload_type = 'status',
        allowed_param = ['status', 'in_reply_to_status_id', 'lat', 'long', 'place_id', 'display_coordinates', 'trim_user'],
        require_auth = True
    )

そして、実際に作成したアプリのソースを、以下に貼っておきます。

consumer_key
consumer_secret
access_token
access_token_secret
は自分のもので置き換えてください。

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

import sys
import os
import logging
import urllib2
import time
import datetime
import locale 

try:
    import json
except ImportError:
    import simplejson as json

import tweepy

########################################
consumer_key="**********"
consumer_secret="********************"
access_token="********************"
access_token_secret="********************"

def get_OAuth():
    try:
        logging.info('get_OAuth start')

        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth_handler=auth, api_root='/1.1')

        # trend情報取得
        trends_available=api.api1_1_trends_available()
        trends_place=api.api1_1_trends_place(id='23424856')

        # 結果の表示 ---------------------
        print "username=" + api.me().name

        # trends_availableの表示 ---------
        print '-' * 30
        HeaderText='%s,%s,%s,%s,%s' % ( 'name', 'placeType', 'country', 'woeid', 'countryCode')
        print HeaderText.encode('utf-8')

        results=trends_available
        for result in results:
            line='%s,%s,%s,%s,%s' % ( result['name'], result['placeType']['name'], result['country'], result['woeid'], result['countryCode'])
            print line.encode('utf-8')

        time.sleep(1)

        # trends_placeの表示 -------------
        print '-' * 30
        results=trends_place
        HeaderText='LocationName=%s,woeid=%s,created_at=%s' % ( results[0]['locations'][0]['name'], results[0]['locations'][0]['woeid'], results[0]['created_at'] )
        print HeaderText.encode('utf-8')

        for trend in results[0]['trends']:
            line='%s' % ( trend['name'])
            print line.encode('utf-8')

        time.sleep(1)

        # statuses_updateの実行 ----------
        d = datetime.datetime.today()
        locale.setlocale(locale.LC_ALL, 'ja')

        message='Updating using OAuth authentication via Tweepy! ' + d.strftime("%Y-%m-%d %H:%M:%S")
        api.api1_1_statuses_update(message)

        return
    except:
        logging.error('get_OAuth ERROR %s', sys.exc_info())
        raise

if __name__ == "__main__":
    try:
#        logging.getLogger().setLevel(logging.ERROR)
        logging.getLogger().setLevel(logging.DEBUG)

        get_OAuth()
        time.sleep(1)

        logging.info('main end')
    except:
        print sys.exc_info()

実行すると、以下のような形で、csv形式で情報表示します。

INFO:root:get_OAuth start
username=********
------------------------------
name,placeType,country,woeid,countryCode
世界中,Supername,,1,None
ウィニペグ,Town,カナダ,2972,CA
オタワ,Town,カナダ,3369,CA
ケベック州,Town,カナダ,3444,CA
モントリオール,Town,カナダ,3534,CA
トロント,Town,カナダ,4118,CA
エドモントン,Town,カナダ,8676,CA
カルガリー,Town,カナダ,8775,CA
バンクーバー,Town,カナダ,9807,CA
バーミンガム,Town,イギリス,12723,GB

   :   :
   (中略)

------------------------------
LocationName=日本,woeid=23424856,created_at=2013-01-05T12:04:29Z
そのものですね
#フォロワーさんで十二支揃うのかどうか
バリタ
おにぎりせんべい
#ダブルフェイス
チロルチョコ
アニスパ
#anispa
アラスカ
岡村さん
INFO:root:main end

(4)問題点

とりあえずいろいろやってみたものの、自分で使うぶんには、これでもいいんだけど、人に使ってもらえるようなアプリを作るときはどうなんだろ。
ユーザにaccess_tokenを入力してもらう必要ないはずなんだけど、Tweepyをつかって、そういった形のアプリ作成できるんだろうか・・・。

TwitterAPIを使ってみるテスト2(OAuth)

前回のエントリで、Twitterトレンド情報を取得してみました。
TwitterAPIを使ってみるテスト(by Python) « Walk on apps.

初めの一歩ということで、その時はログイン不要なAPIを利用していました。
今回は、OAuth認証してTweetしてみるテスト、を試してみます。

使っている環境:
Python2.5.4
Tweepy 1.12
Windows7(64bit)


(1)Twitterのライブラリ
Twitterのライブラリがこちらに紹介されています。
Twitter Libraries

Tweepyが太字になっているので、これがおすすめ?かと思い、使うことにした。

twitter_OAuth01
ダウンロードしたtweepy-master.zipファイルを展開すると、tweepyというディレクトリがあるのでそれをコピーして配置。
同じ場所でアプリ作成する分には、これでライブラリを読込めるので、とりあえずこのまま、インストールせずに使っていきます。


(2)TwitterのDevelopers画面で、My applicationsの作成
Twitterのツイート画面の左下のほうの、「開発者」をクリックします。
twitter_OAuth02

Developers画面で「Sign in」をクリックし、ログイン。

twitter_OAuth03

ログイン後に、My Applicationを選択。

twitter_OAuth04

Create a new applicationボタンをクリック。

twitter_OAuth05

Create an application画面で、Name, Description, Websiteを入力します。

Nameは自分のアプリ名を入力。Twitterの中で一意になる名前でないとダメみたい。

Descriptionはアプリの説明。第3者にアプリを使ってもらうときに表示される。僕の場合、練習なので、とりあえず適当に書きました。
Websiteには、アプリのサポートページとかを書いておくんだと思う。これも第3者にアプリを使ってもらうときに表示される。とりあえず自分のTwitterアカウントのURIを書いといた。

twitter_OAuth06

作成後に、Settingタブを開きます。

twitter_OAuth07

Settingタブの、Application Type設定のAccessを「Read and Write」に設定変更します。

twitter_OAuth08

次に、Detailsタブを開きます。

twitter_OAuth09

Detailsタブの中の、一番下の、Create my access tokenをクリックしaccess tokenを手動で発行します。

通常は、「OAuth認証のやり取りの中でaccess tokenが発行され、アプリ側でそれを保持しておく」といった形になるとおもうけど、今回は練習なので、手動であらかじめ発行しておくことにした。

twitter_OAuth10

そうすると、Detailsタブに、Consumer key, Consumer secret, Access token, Access token secretが表示されているはず。

twitter_OAuth11

とりあえずこれで、アプリ作成の準備が整いました。

Consumer key, Consumer secret, Access token, Access token secretは、アプリ内で設定する必要があるので、メモしておくこと。


(3)ツイートしてみる

ダウンロードしたtweepyの中にExampleがあります。その中のoauth.pyを使います。

まず、Consumer key, Consumer secret, Access token, Access token secretを設定します。
その後、コマンドプロンプトから
python oauth.py

とすると、アカウント名がプロンプトに返ってきて、終了します。

で、Twitterのアカウント画面を見ると、「Updating using OAuth authentication via Tweepy!」と、ツイートされています。

テスト中に、同じ文言でツイートしようとエラーが出て怒られるので、ツイートする文章はそのつど変えてください。

Exampleそのままだけど、ソースを載せておきます。

import tweepy

# == OAuth Authentication ==
#
# This mode of authentication is the new preferred way
# of authenticating with Twitter.

# The consumer keys can be found on your application's Details
# page located at https://dev.twitter.com/apps (under "OAuth settings")
consumer_key=""
consumer_secret=""

# The access tokens can be found on your applications's Details
# page located at https://dev.twitter.com/apps (located 
# under "Your access token")
access_token=""
access_token_secret=""

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

api = tweepy.API(auth)

# If the authentication was successful, you should
# see the name of the account print out
print api.me().name

# If the application settings are set for "Read and Write" then
# this line should tweet out the message to your account's 
# timeline. The "Read and Write" setting is on https://dev.twitter.com/apps
api.update_status('Updating using OAuth authentication via Tweepy!')

(4)問題点

さてとりあえずOAuthは大丈夫でしたが、、
ライブラリの中をよく見てみると、どうやらTwitterAPIのVersion1.0を使っている模様。。
ためしにTwitterトレンドへのアクセスパスを見てみると、ライブラリの中で、
path = ‘/trends/{woeid}.json’

って、書かれていた。Version1.1では、
trends/place.json?id=woeid

となるはず。

そして、Version1.0は、2013年3月5日から使えなくなるみたいです。

https://dev.twitter.com/docs/api/1.1/overview

Deprecation of v1.0 of the API

Most developers won't need to do much work to transition from v1.0 to v1.1, but we want to make sure there is ample time to do so. We will be providing a 6 month window before turning off v1.0. Starting March 5th, 2013, the 1.0 endpoints will no longer be available.

ほかのライブラリを見てみたけど、まだVersion1.1には対応していないように見える。(ここ最近アップデートされていない)

で、悩んだものの、Tweepyのソースにちょこっと追加すれば、Version1.1へのアクセスできるってわかった。(3月になったら、さすがにライブラリのアップデートされるだろうし、とりあえず自分が使いたいエンドポイントはそんなに多くないので、ひとまずこれで暫定対処しようとと思う。)

次回のエントリーで、TwitterAPI Version1.1への対応を書いてみます。


追記
TwitterAPI Version1.1を使ってみました。
TwitterAPIを使ってみるテスト3(TwitterAPI Version1.1) « Walk on apps.

TwitterAPIを使ってみるテスト(by Python)

HappyNewYear
誰よりも早く?、今年初めの投稿です。(下書きしていたものだけど)


TwitterAPIを使ってみたいと思っています。
使う言語はJavaかPythonで迷ったけど、Pythonのほうが書きやすいと思い、Pythonを使うことにした。
(なんでJavaとPythonを候補にしたかというと、GoogleAppEngine上で何か作れないかな~って思うから)

とはいえ、Pythonで外部にアクセスしたことないので、まずは初歩的なことを試してみることにします。
やってみることは、「TwitterトレンドAPIにアクセスして、日々のトレンド情報取得」にしてみます。

具体的には、
(a)TwitterトレンドAPIにHTTPリクエスト送信
(b)JSON形式データの読込

を行ってみます。

使っている環境:
Python2.5.4
Windows7(64bit)


(1)はじめに
今回は、練習としてPythonの標準機能でできることを試してみるつもり。
なのでSDKは使いません。

OAuth認証とか、HTTPSアクセスとか行うときはSDKを使うことになると思う
ちなみに、TwitterAPIを使うときのSDKはこちらに公開されています。

Twitter Libraries

(注)
今回使うTwitterトレンドAPIは、API Version1.0をつかっています。
現状、Version1.1が提供されており、将来的にはVersion1.0は使えなくなると思います。
ただ今回は、Pythonの練習なので、OAuth認証が不要なVersion1.0を使うことにしました。


(2)TwitterトレンドAPI仕様確認

まず、マニュアルはこちら
GET trends/:woeid
GET trends/available

使い方は、
以下のような形式でリクエスト送信することで、データを受信できます。
「http://api.twitter.com/1/trends/:woeid.format」
ここでは、
:woeidには、 「Yahoo! Where On Earth ID」
.formatには、データ形式
になってる。
ためしに日本全体のトレンドを見てみる。ブラウザに
「http://api.twitter.com/1/trends/23424856.json」
と入力するとJSON形式でデータが返ってくる。

woeidはYahooが決めたものらしい。ID自体は世界中の地域に割り振られているようだが、Twitterトレンドで対応している地域が決まっているので、次にそれを確認する必要がります。

以下のアドレスにアクセスすると、利用できる地域の一覧がJSON形式で表示されます。(ちなみにマニュアルによるとxml形式もOKみたいなんだけど、試してみるとエラーになった。)
「http://api.twitter.com/1/trends/available.json」

まずは、この利用できる地域の一覧から、日本のID一覧をピックアップするものを作成してみることにします。
というわけで、次のコーディングに移ります。

(参考サイト)
TwitterトレンドAPIを使って最新のtwitterトレンドワードを取得してみる – yeyue’s diary:


(3)Pythonコーディング(GET trends/available)

PythonでHTTPリクエストを行うときは、ライブラリurllib2を使い、urlopenメソッドを使うらしい。

 urllib2.urlopen(URL)

試してみると確かにデータ取得できるんだけど、表示内容がすべて英語になってしまった。
ブラウザだと日本語になるのになんでかなって思ったんだけど、HTTPヘッダで指定してないからだって気付いた。

というわけで、HTTPヘッダに以下を追記することにします。
Accept-Language: ja,en

Pythonのコードは以下のような書き方になる。

            req = urllib2.Request(url)
            req.add_header('Accept-Language', 'ja,en')
            resultUrlOpen = urllib2.urlopen(req)

つぎにJSON形式データの読込です。
僕はPython2.5.*を使っているため、Python標準ライブラリにjsonモジュールが入っていませんでした。
(Python2.6以上では、標準で使える模様)
そのため、simplejsonというライブラリを使います。ただ、Python2.6以上でも、そのままつかえるように、ライブラリimport文を以下のように書いておきます。

try:
    import json
except ImportError:
    import simplejson as json

で、読込み(parse)は、jsonクラスのloadメソッドを使う。

results = json.load( JSON_DATA, encoding='utf8')

こうするとresultに、ハッシュ形式で格納される。(Pythonで言うとdictionary形式ですかね。

(参考サイト)
忘れがちな記憶へ Twitter Search API with Python

さて、コードをまるごと貼り付けておきます。

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

import sys
import os
import logging
import urllib2

try:
    import json
except ImportError:
    import simplejson as json

########################################

SEARCH_URL='http://api.twitter.com/1/trends/available.json'

def get_url():
    try:
        logging.info('get_url start')
        url=SEARCH_URL
        resultUrlOpen = None

        try:
            logging.info('url:%s', url)

            req = urllib2.Request(url)
            req.add_header('Accept-Language', 'ja,en')
            resultUrlOpen = urllib2.urlopen(req)
            return resultUrlOpen

        except urllib2.HTTPError:
            logging.warning('urllib2 HTTPError:%s', sys.exc_info())
            pass

        except urllib2.URLError:
            logging.warning('urllib2 URLError:%s', sys.exc_info())
            pass

        if None == resultUrlOpen:
            logging.error('resultUrlOpen==None')

        return None

    except:
        logging.error('get_url ERROR %s', sys.exc_info())
        raise

def read_json(wfp, resultUrlOpen):
    try:
        logging.info('read_json start')

        results = json.load( resultUrlOpen, encoding='utf8')

        if len(results) == 0:
            return

        HeaderText='%s,%s,%s,%s,%s' % ( 'name', 'placeType', 'country', 'woeid', 'countryCode')
        wfp.write('%s\n' % HeaderText.encode('utf-8')) #ファイル書き込み

        for result in results:

            line='%s,%s,%s,%s,%s' % ( result['name'], result['placeType']['name'], result['country'], result['woeid'], result['countryCode'])
            wfp.write('%s\n' % line.encode('utf-8')) #ファイル書き込み

        return
    except:
        logging.error('read_json ERROR %s', sys.exc_info())
        raise

if __name__ == "__main__":
    try:
#        logging.getLogger().setLevel(logging.ERROR)
        logging.getLogger().setLevel(logging.DEBUG)

        wfp = open('ret_tweet_trend_available.txt', 'w')

        resultUrlOpen = get_url()
        read_json(wfp, resultUrlOpen)

        wfp.close()

        logging.info('main end')
    except:
        print sys.exc_info()

実行すると、ret_tweet_trend_available.txtファイルに、CSV形式で一覧を出力します。

それをエクセルに貼り付けてフィルタしてみましたので、貼っておきます。

name    placeType    country    woeid    countryCode
北九州  Town         日本       1110809  JP
千葉    Town         日本       1117034  JP
福岡    Town         日本       1117099  JP
広島    Town         日本       1117227  JP
川崎    Town         日本       1117502  JP
神戸    Town         日本       1117545  JP
名古屋  Town         日本       1117817  JP
札幌    Town         日本       1118108  JP
仙台    Town         日本       1118129  JP
高松    Town         日本       1118285  JP
東京    Town         日本       1118370  JP
横浜    Town         日本       1118550  JP
沖縄    Town         日本       2345896  JP
大阪    Town         日本       15015370  JP
京都    Town         日本       15015372  JP
日本    Country      日本       23424856  JP

(4)Pythonコーディング(GET trends/:woeid)

日本のwoeid、23424856を使って、トレンド取得してみる。

やり方は、「GET trends/available」へアクセスしたときと同じなので、いきなりソースコードを貼り付けておきます。

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

import sys
import os
import logging
import urllib2

try:
    import json
except ImportError:
    import simplejson as json

########################################

SEARCH_URL='http://api.twitter.com/1/trends/23424856.json'

def get_url():
    try:
        logging.info('get_url start')
        url=SEARCH_URL
        resultUrlOpen = None

        try:
            logging.info('url:%s', url)

            req = urllib2.Request(url)
            req.add_header('Accept-Language', 'ja,en')
            resultUrlOpen = urllib2.urlopen(req)
            return resultUrlOpen

        except urllib2.HTTPError:
            logging.warning('urllib2 HTTPError:%s', sys.exc_info())
            pass

        except urllib2.URLError:
            logging.warning('urllib2 URLError:%s', sys.exc_info())
            pass

        if None == resultUrlOpen:
            logging.error('resultUrlOpen==None')

        return None

    except:
        logging.error('get_url ERROR %s', sys.exc_info())
        raise

def read_json(wfp, resultUrlOpen):
    try:
        logging.info('read_json start')

        results = json.load( resultUrlOpen, encoding='utf8')

        if len(results) == 0:
            return

        HeaderText='LocationName=%s,woeid=%s,created_at=%s' % ( results[0]['locations'][0]['name'], results[0]['locations'][0]['woeid'], results[0]['created_at'] )
        wfp.write('%s\n' % HeaderText.encode('utf-8')) #ファイル書き込み

        for trend in results[0]['trends']:
            line='%s' % ( trend['name'])
            wfp.write('%s\n' % line.encode('utf-8')) #ファイル書き込み

        return
    except:
        logging.error('read_json ERROR %s', sys.exc_info())
        raise

if __name__ == "__main__":
    try:
#        logging.getLogger().setLevel(logging.ERROR)
        logging.getLogger().setLevel(logging.DEBUG)

        wfp = open('ret_tweet_trend.txt', 'w')

        resultUrlOpen = get_url()
        read_json(wfp, resultUrlOpen)

        wfp.close()

        logging.info('main end')
    except:
        print sys.exc_info()

実行すると、ret_tweet_trend.txtファイルに、こんな感じで出力されます。

LocationName=日本,woeid=23424856,created_at=2012-12-31T19:16:32Z
今年もよろしく
おめでとうございます
Happy New Year
New Year
初日の出
お世話になりました
年越し
2012年
ジャニ
ありがとうございました

とりあえずこれで基本的なところは良しとして、今後もっと本格的にAPIを使ってみようと思う。


追記
TwitterAPIへのOAuth認証を試してみました。
TwitterAPIを使ってみるテスト2(OAuth) « Walk on apps.