2007/05/24

Recent entries from same category

  1. WebService::SimpleをLuaで...
  2. ただ単に、「Lua」で「るわ」を検索したくなった。それだけ
  3. Luaでtwitter発言をWebScraperする

久しく、プログラミングの話をしてなかったのでリハビリがてら...

もう既に、色んな方が、色んな言語で、twitterサーバとおしゃべりするライブラリ、アプリケーションを作っていらっしゃいます。

Twitter Fan Wiki Scripts によると
  • Applescript
  • Jabber
  • Perl
  • PHP
  • Python
  • .NET
  • Ruby
など、著明なスクリプト言語では、既にライブラリやアプリケーションとして出来上がっています。

私も愛用している「twitterMobile」も、phpで開発された高機能ライブラリ「Services_Twitter」を使って動作しています。

いやぁ皆さん早いなぁ...
ブログネタも無くなるってもんです。汗

が、しかし...

ここで登場するのがXtalです。ウソです。

ここで登場するのがLuaです。

Luaは簡素で、組込みに向いていると言われている程、小さな言語ですが
  • 連想配列
  • 型の遅延バインディング
  • ガベージコレクション
など、かなりハイレベルな機能も持ち合わせています。
がやはり、ネットワーク通信やXML解析を、標準機能で実装されている訳ではありませんので、どうしても拡張ライブラリが必要になります。
Lua単体で出来ることって言えば、ウメボシの個数を数えるくらいの事しか出来ません。(意味不明

今回は、LuaForgeにも登録されている、以下の拡張ライブラリを使用して、twitterとおしゃべりできるような物を作って行きます。

  • LuaExpat
  • Expatライブラリを使用してLuaからXMLを操作出来る拡張ライブラリ
  • LuaSocket
  • HTTPやFTP等、各種プロトコルに対応した拡張ライブラリ

まず、通信部分を作って行きましょう。
local get_statuses_url = "http://twitter.com/statuses/friends_timeline.xml"
local auth = string.format("%s:%s", mail, pass)
local chunk = {}

b, c = http.request {
  method = "GET",
  url = get_statuses_url,
  headers = { authorization = "Basic " .. (mime.b64(auth)) .. "==" },
  sink = ltn12.sink.table(chunk)
}
local xml = table.concat(chunk)
LuaSocketのmimeライブラリでBasic認証ヘッダを生成し、LTN12形式のsinkチャンクで文字列化しました。

次にこのXMLをLuaExpatを使用して解析します。
local statuses = lom.parse(xml)

for n1, v1 in pairs(statuses) do
  if v1["tag"] == "status" then
    local date = ""
    local user = ""
    local text = ""
    for n2, v2 in pairs(v1) do
      if v2["tag"] == "created_at" then
        date = get_node_text(v2)
      elseif v2["tag"] == "text" then
        text = get_node_text(v2)
      elseif v2["tag"] == "user" then
        for n3, v3 in pairs(v2) do
          if v3["tag"] == "screen_name" then
            user = get_node_text(v3)
          end
        end
      end
    end
    print(date)
    print(user .. ":" .. text)
    print("")
  end
end
以上でLuaからtwitterのステータスがコンソール出力されます。
うーむ。Expatを使ってXMLを解析する際に出現する、ループネストがイヤらしい...

この処理を使って、実際にステータスを取得してみた結果が、コレだ!
ワンツースリー!

Wed May 23 16:54:44 +0000 2007
*******:MHP2+Xlinkでオンラインプレイやれたぜ。これは楽しい。

Wed May 23 16:52:50 +0000 2007
*****:Browsing: ニコニコ動画(γ)‐DAKARA CM「送別会篇」 (http://www.nicovideo.jp/watch/sm195564)

Wed May 23 16:45:01 +0000 2007
********:サーコー!サーコー!ワンモアタィム!ヒィアウィゴー!http://www22.atwiki.jp/onemoretime/

Wed May 23 16:42:29 +0000 2007
********:ねこがふてねしている

Wed May 23 16:34:04 +0000 2007
******:今更Web::Scraperつかった。すげべんり。http://tinyurl.com/27aaar

Wed May 23 16:30:37 +0000 2007
******:@******** おやすみなさいです _TL_

Wed May 23 16:28:41 +0000 2007
********:眠いので寝ます。おやすみなさい。<(_ _)>

Wed May 23 16:28:17 +0000 2007
*****:寝れなかったので起きてみた。
※ユーザ名は消してあります。

あとはステータス書き込み処理です。

実はLuaはスクリプト内部のエンコーディングが決められていません。ましてや文字単位の処理などは標準では出来ません。
※最近のLuaは知りません。もしかしたらオフィシャルとしてutf-8か何かに変わったかも知れません。

ですので、今回のステータス書き込み処理では、ステータス文字列がutf-8である前提で記述しています。

local update_status_url = "http://twitter.com/statuses/update.xml"
local auth = string.format("%s:%s", mail, pass)
local chunk = {}

update_status_url = string.format("%s?status=%s", update_status_url, url.escape(status))
b, c = http.request {
  method = "POST",
  url = update_status_url,
  headers = { authorization = "Basic " .. (mime.b64(auth)) .. "==" },
  source = nil
}

ステータス取得時と同様ですが、今回はsocket.urlライブラリでエスケープしたクエリ文字列を送信しています。

いやぁ、twitterのAPIって簡素で良い!
Lua-Gtk2と組み合わせて、GUIを作るってのもいいかも知れません。

一応、上記のスクリプトソースをダウンロード出来るようにしておきます。
ソース内のメールアドレスとパスワードを変更すれば、twitterコマンドラインプログラムとして動作します。
ただし、utf-8限定です。

どうぞパクって行って下さい。

ダウンロード:
Posted at by