Twitterのつぶやきをバックアップするツールをscalaで書いたの
Scalaスケーラブルプログラミングが書店にはもう並んでいるのにいまだにamazonからの発送メールが来ていないゆろよろデスおつかれザマァm9(^Д^)です。
自分がついったをはじめて早1年半が経ちます。Postが3000を超えたんで、いままでの自分のつぶやきをバックアップしておこうと思いました。
ついったのバックアップをとるための便利なサービスが世の中にはいっぱいあるんですが、scalaの勉強がてらに書いてみました。
ここに置いてあります。
yuroyoro/TwitBackupper · GitHub
使い方
まずgitからソース一式落とします。つぎにmavenでコマンドうちます。終わり。
$ git clone git://github.com/yuroyoro/TwitBackupper.git $ cd TwitBackupper $ mvn scala:run -DaddArgs="-i|君のIDだ"
実行するとカレントディレクトリにxmlで過去のstatusが保存されます。
csvにしたい場合は、こんな感じで。
$ mvn scala:run -DaddArgs="-i|君のIDだ|-t|csv"
中身のはなし
オプションでいろいろ出来るようにしたらコードがえらい汚くなったのが反省です。ってか半分近くがコマンドラインオプションの解析だよあーメンドクセェ。
シンプルに実装するなら、こんな感じになると思います。都合30行です。
package com.yuroyoro.twitbackupper import scala.xml._ import scala.io.Source object Sample { def main( args:Array[String] ):Unit= { val twitterId = args.first lazy val userTimelineUrl = "http://twitter.com/statuses/user_timeline/%s.xml?count=200".format( twitterId ) def getUserTimeline( maxId:Long , cnt:Int):Unit = { // UserTimelineを取得する val url = userTimelineUrl + { if( maxId > 0 ) "&max_id=" + ( maxId - 1 ) else ""} println( url ) val source = Source.fromURL( url ) // XML取得 val xml = XML.loadString( source.getLines.mkString ) xml \\ "status" size match { // statusが取れなくなったら終了 case 0 => None // XMLと、取得した中で最小のstatus idをTupleにして返す case _ => XML.saveFull( "%s_user_timeline_%d.xml".format( twitterId, cnt ), xml, "UTF-8", false, null) getUserTimeline( (xml \\ "status" \ "id" last).text.toLong , cnt + 1) } } getUserTimeline( -1 , 0) } }
ちょっとコードの解説します。
val source = Source.fromURL( url )
TwitterのAPIのURLを引数に、scala.io.SourceオブジェクトのfromURLを利用してSourceオブジェクトを取得しています。
scala.io.SourceクラスはjavaのInputStreamをちょっと使いやすくしたようなもんです。(そうでもないかも?)
val xml = XML.loadString( source.getLines.mkString )
SourceオブジェクトからXMLの文字列を取得して、scala.xml.XMLオブジェクトを利用してscala.xml.Elemオブジェクトに変換しています。
scalaでXMLリテラルを書くと、実態はこのscala.xml.Elemオブジェクトになるのですよ。
xml \\ "status" size match { // statusが取れなくなったら終了 case 0 => None // XMLと、取得した中で最小のstatus idをTupleにして返す case _ => XML.saveFull( "%s_user_timeline_%d.xml".format( twitterId, cnt ), xml, "UTF-8", false, null) getUserTimeline( (xml \\ "status" \ "id" last).text.toLong , cnt + 1) }
xmlの中から、xml \\ "status" sizeでstatusタグの数を数えてます。結果をパターンマッチングさせて0だったら終了。
statusが取れてたら、XMLオブジェクトのsaveFullメソッドでxmlそのものをファイルとして保存してます。
保存した後、再帰でもう一度getUserTimelineメソッドを呼び出します。
getUserTimelineメソッドの引数に、次のAPIの呼び出しで指定するmax_idを渡しています。
(xml \\ "status" \ "id" last).text.toLong
()の中は、xml中のstatusタグをscala.xml.NodeSeqで取得して最後のstatusタグの子要素のidタグを選択してます。idタグに対して textでタグの中身を取ってlongに変換です。
簡単ですね。もっと短く書けるでしょう。