まったりいんふぉまてぃくすめもらんだむ

主にプログラミング関係のメモに使うかもしれないしそうでないかもしれない

Pythonで端末からtwitterにpostする

最近プログラミングを全くやってなかった(というか僕はもともと日常的にプログラムを書いてる人間ではない)のと、自分のクライアントからpostするのってなんかかっこいいよね()というわけでやってみることに。
とりあえず今回の目的は端末からpostするだけだけど、僕が気に入ってるJanetterにはLinux版がないし、本格的なクライアントとは言わないまでもリストが普通に読めるぐらいにはできたらいいなぁ。


まずはこのエントリの内容とは関係ないけど便利だと聞いたpipを導入しておく。pipの使い方についてはpipの使い方 - そこはかとなく書くよ。あたりが詳しそう。基本的にはsudo pip installとpip freezeだけでよさそうかな。

さてここから本題。python-twitterモジュールを使うと簡単にできるよ、ということを事前に聞いていたので、その方向で。

パッケージのインストール。

$ sudo pip install python-twitter

依存パッケージのOAuth2も勝手にインストールしてくれて素敵。

次にクライアントをCreate an application | Twitter Application Managementに登録する。OAuth認証時に渡すコンシューマキーとコンシューマシークレット、それと自分のアカウントのアクセスキー&シークレットも一緒にここで取得できた。

準備ができたら、あとはpython-twitter - A python wrapper around the Twitter API - Google Project Hostingとか参考にしながら書いていく。最初はとりあえずpostできればいいやぐらいで考えてたけど、作ってるうちに微妙にのめりこんできて最終的にこんな感じになった。

twicli.py

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

import sys
import datetime
import twitter
from optparse import OptionParser

# -----設定-----                                                                                                                                                             
C_KEY = 
C_SECRET = 
A_TOKEN = 
A_SECRET = 
MYNAME = 
# --------------                                                                                                                                                             

class Client(object):
    def __init__(self):
        self.client = twitter.Api(consumer_key=C_KEY,
                                  consumer_secret=C_SECRET,
                                  access_token_key=A_TOKEN,
                                  access_token_secret=A_SECRET)

    def tl(self, i=10):
        """ TL取得                                                                                                                                                           
                                                                                                                                                                             
        引数で指定した数だけTLを取得し表示                                                                                                                                   
        """
        tl = self.client.GetFriendsTimeline(count=i)
        tl.reverse()
        for stat in tl:
            username = u"@"+stat.user.screen_name+u" "+stat.user.name
            print u"-------------------------------------------".encode("utf-8")
            print username.encode("utf-8")
            print stat.text.encode("utf-8")
            # 時刻の処理                                                                                                                                                     
            # 標準時になっているので日本時間に直す                                                                                                                           
            t_list = stat.created_at.split(" ")
            t_cut = " ".join(t_list[:4] + t_list[5:])  # オフセット部分をカット                                                                                              
            dt = datetime.datetime.strptime(t_cut, "%a %b %d %H:%M:%S %Y")
            dt += datetime.timedelta(hours=9)  # 9時間すすめる                 

            print dt.strftime("%m/%d %H:%M:%S").encode("utf-8")

    def post(self, s):
        """ postする                                                                                                                                                         
        """
        ret = self.client.PostUpdate(s.decode("utf-8"))
        print u"posted: ", ret.text

if __name__ == "__main__":
    usage = ("usage: python %prog [-t COUNT] [TWEET]")
    parser = OptionParser(usage)
    parser.add_option("-t",
                      action="store", type="int", dest="count",
                      default=None, metavar="COUNT",
                      help="get timeline by count")

    (options, args) = parser.parse_args()

    cli = Client()
    if (options.count == None):  # -tオプションがない場合は、postする                                                                                                        
        if len(args) == 0:
            parser.error("please input tweet")
        else:
            cli.post(args[0])
    else:  # -tオプションが付いていた場合、TLを取得する                                                                                                                      
        cli.tl(options.count)
         

ファイル名が既に存在するクライアント名だしApiクラスの使い方のあたりとか明らかに無駄なことしてる気がするけど、自分しか使わないので気にしない。
短いコードだけどひさしぶりにちゃんとPython書いたのですごい時間かかった。

手こずった部分はstatus.created_at(postされた日時)が標準時になってたのを日本時間になおすのと、あとは取得したTLをlessに渡そうと思ったときに起きた文字コード周りのエラー。
前者は処理しにくいオフセット部分(+0000みたいな)を削ってdatetimeに渡して処理、後者はUnicodeDecodeError/UnicodeEncodeErrorに悩まないPython 2.x プログラミング - atsuoishimotoの、もう http://www.gembook.orgに引っ越しちゃったよ日記がわかりやすかった。やったこととしてはprint文の後に適当に.encode("utf-8")をつけまくっただけ(

以下自分用使い方メモ。
まずは対話環境で使う場合。

>>> import twicli
>>> cli = twicli.Client()
>>> cli.tl(30)  # TLの取得
>>> cli.post("hogehoge")  # post

twitter用の端末を立ち上げてそこでオブジェクト作っとく、という使い方をすればいいかも。

端末から実行する場合。

$ python twicli.py -t 30  # TLの取得
$ python twilci.py "fugafuga"  # post

いちいち認証しなおすのであんまりよくない?エイリアス登録しとくと便利かな。

まぁpostはともかくTL取得機能はほとんどカスみたいなもんだけど、今後暇があるときにぼちぼち改良していく感じで。