2011年09月18日

メモ書き

こんなのを書く。

scala.sys.processを使ってみる
http://www.mwsoft.jp/programming/scala/scala_process.html

上のを書いていてふと思いついたので、試しにTwitterのStreamingAPIの内容をcurlでさらっと取ってファイルに書いてみる。

ScalaのデフォルトのJSON機能(微妙な子)を使ってしまっていたり、日本語判定が恐ろしいほどに適当だったりするけど、普通はTwitter4jとか言語判定ライブラリを使うだろってとこなので、適当なままで良しとする。

import scala.util.parsing.json.JSON
import sys.process._
import java.io.{ BufferedReader, InputStreamReader, BufferedWriter, FileWriter }

object TwitterStreaming extends App {

// ユーザ名とパスワード
val user = "user_name"
val pass = "password"

// 出力するファイル
val writer = new BufferedWriter(new FileWriter("tweet.txt", true))

// JSON文字列をパースして適当にMapにする(あまりちゃんとやってない)
def parse(line: String): Map[String, String] = {
var map = collection.mutable.HashMap[String, String]()
JSON.parse(line).get foreach {
_ match {
case x: Tuple2[String, String] => map += x._1 -> x._2
case _ => {}
}
}
map.toMap
}

// なんか適当にエスケープしてファイルに出力する
def write(id: String, createdAt: String, text: String) {
val s = Array("t", "n", "r")
if (text matches ".*[あ-んアーン].*") {
val sText = (0 to 2).foldLeft(text) { (x, y) => x.replaceAll("\\" + s(y), "\\\\" + s(y)) }
writer.write(id + "\t" + createdAt + "\t" + sText + "\n")
}
}

// Twitterから来た情報を受け取って吐き出す処理を定義したProcessIO
val pio = new ProcessIO(
in => {},
out => {
val reader = new BufferedReader(new InputStreamReader(out))
def readLine(counter: Int = 1): Unit = {
val line = reader.readLine()
if (line != null) {
val map = parse(line)
try if (Array("id_str", "created_at", "text") forall (map contains _)) {
write(map("id_str"), map("created_at"), map("text"))
if (counter % 10000 == 0) writer.flush()
} catch { case e => e.printStackTrace }
readLine(counter % 10000 + 1)
}
}

readLine()
},
err => {})

// 実行
val command = "curl https://stream.twitter.com/1/statuses/sample.json? -u%s:%s" format (user, pass)
val process = command run pio
process.exitValue()
}