tw.pyを少し拡張してみた

日頃、シェルの上で作業を行うことが多いので、
コマンドラインで動作するTwitterクライアント」
を考えていました。


そんなところ、こちらの記事を発見し、
良いもの。悪いもの。: コマンドラインで動作するOAuth対応TwitterクライアントをPythonで作ってみた
ここで紹介されている「tw.py」を参考に、少し拡張してみました。



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

import sys, os, pickle
from oauthtwitter import *

# http://twitter.com/oauth_clients から「OAuthクライアント」の登録を行ってください
CONSUMER_KEY    = ""
CONSUMER_SECRET = ""

# キーファイルを保存するパスを指定してください(この場所でなくても構いません)
KEY_FILE        = "/home/ユーザ名/.tw/twitter_key.dat"

# プロキシの設定が必要な場合は、こちらで設定してください
PROXY_SERVER = '' # 例 PROXY_SERVER = 'proxy.example.com:8000'
USER = ''
PASS = ''

class MyApi(OAuthApi):
  def _GetOpener(self):
    opener = self._urllib.build_opener()

    if PROXY_SERVER != '':
      p_h = self._urllib.ProxyHandler({'http': PROXY_SERVER})
      opener.add_handler(p_h)
      passmgr = self._urllib.HTTPPasswordMgrWithDefaultRealm()
      passmgr.add_password(None, PROXY_SERVER, USER, PASS)
      a_h = self._urllib.ProxyBasicAuthHandler(passmgr)
      opener.add_handler(a_h)

    return opener

  def PrintPublicTimeline(self):
    for status in self.GetPublicTimeline():
      print status.GetUser().GetScreenName() + ":", status.GetText().encode("utf-8", "replace")

  def PrintFriendsTimeline(self):
    for status in self.GetFriendsTimeline(count=20):
      print status.GetUser().GetScreenName() + ":", status.GetText().encode("utf-8", "replace")

  def PrintReplies(self):
    for status in self.GetReplies():
      print status.GetUser().GetScreenName() + ":", status.GetText().encode("utf-8", "replace")

def twitter():
  if os.path.isfile(KEY_FILE):
    access_token = pickle.load(file(KEY_FILE))
  else:
    tw = MyApi(CONSUMER_KEY, CONSUMER_SECRET)
    request_token = tw.getRequestToken()
    authorization_url = tw.getAuthorizationURL(request_token)
    print authorization_url
    tw = MyApi(CONSUMER_KEY, CONSUMER_SECRET, request_token)
    oauth_verifier = raw_input("What is the PIN? ")
    access_token = tw.getAccessTokenWithPin(oauth_verifier)
    pickle.dump(access_token, file(KEY_FILE, "w"))
  return MyApi(CONSUMER_KEY, CONSUMER_SECRET, access_token)

def main(args):
  tw = twitter()
  if len(args) > 1:
    if args[1][0] == '-':
      if args[1][1:] == 'p': tw.PrintPublicTimeline()
      elif args[1][1:] == 'f': tw.PrintFriendsTimeline()
      elif args[1][1:] == 'r': tw.PrintReplies()
      else: tw.PrintFriendsTimeline()
    else:
      post = " ".join(args[1:])
      tw.PostUpdate(post.decode("utf-8"))

  else:
    tw.PrintFriendsTimeline()

if __name__ == "__main__":
  main(sys.argv)

Mercurialがインストールされていれば、Bitbucketからもダウンロードできます。

追加したところ

追加したところとしては、次の箇所が挙げられます。

  • 自分宛のリプライを表示する機能
  • パブリックタイムラインを表示する機能
  • 文字コードUTF-8へ変更
  • プロキシに対応

インストール方法

0.必須モジュールのインストール

私の環境(Ubuntu 10.04)を対象に説明します。
最低限Pythonの実行環境が整っていることは前提条件とします。

$ python -V
Python 2.6.5

Pythonは2.6以上を使用したほうが良いかもしれません。



まずは、python-twitterモジュールをインストールします。
(私の場合は、後ほど説明するsetuptoolsを使用したインストールの際にインストールされるpython-twitterだと、うまく動作しませんでした。)

$ sudo apt-get install python-twitter

次に、oauth-python-twitterをインストールするために、
「setuptools」をインストールします。

$ wget http://peak.telecommunity.com/dist/ez_setup.py
$ sudo python ez_setup.py

最後に、oauth-python-twitterをインストールします。
《ダウンロード》

$ svn export http://oauth-python-twitter.googlecode.com/svn/trunk/ oauth-python-twitter

※「svn」がインストールされていない場合は次のコマンドを実行してsvnをインストールしてください。

$ sudo apt-get install svn

《少しソースコードを改変》
oauth-python-twitter/oauthtwitter/__init__.py の191行目あたりにある
「getAccessToken」メソッドの定義の下に次の関数定義を加えてください。

    def getAccessToken(self, url=ACCESS_TOKEN_URL):
        token = self._FetchUrl(url, no_cache=True)
        return oauth.OAuthToken.from_string(token) 

    # --- ここから下を加える ---
    def getAccessTokenWithPin(self, pin, url=ACCESS_TOKEN_URL):
        token = self._FetchUrl(url, parameters={"oauth_verifier": pin}, no_cache=True)
        return oauth.OAuthToken.from_string(token)
    # --- ここから上を加える ---

    def getRequestToken(self, url=REQUEST_TOKEN_URL):
        '''Get a Request Token from Twitter
        
        Returns:
          A OAuthToken object containing a request token
        '''
        resp = self._FetchUrl(url, no_cache=True)
        token = oauth.OAuthToken.from_string(resp)
        return token

《インストール》
次のコマンドを実行してインストールを行います。

$ cd oauth-python-twitter/
$ python setup.py build
$ sudo python setup.py install

UbuntuでのPythonモジュールインストール方法に関しては
こちらの記事がとても参考になりました。

1.「Consumer key」・「Consumer secret」の取得

こちらからアプリケーションの登録を行ってください。

アプリケーション登録申請の際に気をつけなければならない項目は次のとおりです。

アプリケーションの種類 「クライアントアプリケーション」を選択
標準のアクセスタイプ 「Read & Write」を選択
Twitterでログインする 「はい、Twitterをログインに使用します。」にチェックを入れる

その他の項目は適当で構いません。



登録申請が完了すると、「Application Details」というページで次の2つを入手できます。

  • Consumer key
  • Consumer secret

それぞれの文字列を、先ほど挙げたプログラム冒頭の次の部分で設定してください。

# http://twitter.com/oauth_clients から「OAuthクライアント」の登録を行ってください
CONSUMER_KEY    = ""
CONSUMER_SECRET = ""
2.認証番号(PIN)の入力

冒頭で挙げたソースコードの次の部分に、アクセストークンを保存するファイルのパスを指定してください。

# キーファイルを保存するパスを指定してください(この場所でなくても構いません)
KEY_FILE        = "/home/ユーザ名/.tw/twitter_key.dat"

※パスを指定する際に、「~/」のような短縮記法は使わないでください。うまくいかないようです。




使い方

指定できるオプションと振る舞いは次のとおりです。

-p パブリックタイムラインを表示
-f フレンドタイムラインを表示
-r 自分へのリプライを表示

※何もオプションを指定せずに実行した場合、フレンドタイムラインが表示されます。



オプションではない引数を第1引数に指定すると、その文字列をつぶやきます。

$ tw "こんにちは"
# 「こんにちは」というつぶやきが投稿される

また、いくつか引数がある場合はそれらを連結してつぶやきます

$ tw @hogehoge "それはないだろう"
# 「@hogehoge それはないだろう」というつぶやきが投稿される

問題点

自分なりに使いやすくするために色々と機能を追加してみましたが、
いくつかまだ微妙なところがあります。


  • 通常通りのつぶやきでしかリプライできないため、リプライに対する返信ができない
    • 現在の状態では「@返信相手 いいたいこと」というつぶやきをすることでしか返信ができないため、どのつぶやきに対するものなのかが分からない
  • エラー処理をしていない
    • すみません、try-catchくらいは早めに追加します(汗)
  • 設定が同じソースコード内に記述されている
    • プロキシの設定とかも含めて、設定は「~/.tw/」内に設定ファイルを作成するとか、別ファイルに切り分けたいです

参考にさせていただいた記事

既に紹介した記事も含めて、参考にさせてもらった記事を改めて紹介します。

蛇足(タイムラインを追うには)

このコマンド自体は「今のタイムライン」を1回表示して終わりなのですが、
「一定間隔で繰り返す」というコマンドと組み合わせることでリアルタイムにタイムラインを追うことができます。



そのようなコマンドで代表的なのは watch というコマンドですが、
Ubuntu 10.04にインストールされていたものでは日本語が文字化けしてしまいました。



そこで、topless というコマンドを使います。
残念ながら、apt-get では落ちてこなかったため、
そのような場合はこちらからシェルスクリプトをダウンロードして、パスの通った場所に置いてください。

toplessもwatchも、引数に繰り返し実行したいコマンドを指定するだけです。

$ topless '繰り返したいコマンド'

フレンドタイムラインを追いたい場合は次のようにします

$ topless 'tw'

※topless コマンドはデフォルトで、『2秒に1回』の更新を行います。
 ですが、こちらの記事によると、TwitterAPIの制限は『1時間に350回が基本』とのことなので、
 長時間実行し続けるとAPI制限にぶつかります、ご注意ください。

また、パブリックタイムラインの中から日本語のものだけを監視する場合は
次のようなコマンドが使えます。(取りこぼしも多分にありそうですが・・・)

$ topless 'tw -p | grep -e "[あ-んア-ン]"'