ひとりぶろぐ

価値ある情報をユーザー視点で発信するブログ

iPadのステータスバーにbuzztterや円相場を表示

      2016/03/16

先日アップしたStatusBarCustomClockは、テキストファイルの中身をステータスバーに表示でき、10秒ごとに更新しているので、工夫次第で面白いことができますよ。
iPhoneではちょっと無理がありますが、iPadならステータスバーが広大ですから、いろいろなものが表示できます。

活用例ということで、上掲のスクリーンショットのように、TwitterのBuzz Wordを集計している興味深いサイト、buzztterの1位から3位まで、また円相場をStatusBarCustomClockに表示する例をお目にかけます。(続きは[MORE]から)

SBCCScriptのインストール

すぐに体験できるサンプルをNew野良リポジトリにアップしておきましたので、試してみてください。「SBCCScript」という名前で登録してあります。
インストール後、StatusBarCustomClockの設定のDate Formatに、テキストの埋め込みを指示するマクロ「TXT」を追加してrespringします。
TXTと書いておくと、それがテキストファイルの内容と置き換えられるのです。

デフォルトでは、「/var/mobile/sbcc.txt」の存在を確認し、あればその内容を読み込みます。SBCCScriptは、その内容を自動的に更新するスクリプトをインストールします。

SBCCScriptは、冒頭のスクリーンショットのように、ドル/円相場とbuzztterのトップBuzz Wordを表示するサンプルとなっているので、一定の実用度はあると思います。そのまんま使うのでも構いませんが、もっと活用しましょう。

SBCCScriptの仕組み

SBCCScriptは、以下のファイル群から成ります。

/System/Library/LaunchDaemons/com.hitoriblog.sbccscript.plist
/usr/bin/sbcc.rb
/usr/bin/sbcc_dummyconnect

また、パッケージのpostinst、prermの中で以下のコマンドを実行しています。

インストール時

launchctl load -w /System/Library/LaunchDaemons/com.hitoriblog.sbccscript.plist

アンインストール時

launchctl unload -w /System/Library/LaunchDaemons/com.hitoriblog.sbccscript.plist

/usr/bin/sbcc.rbは、拡張子からも分かる通りRubyスクリプトです。
このパッケージはRubyに依存しているので、Rubyがインストールされていなかったらいっしょにインストールされます。

インストール時に上記コマンドを実行することで、com.hitoriblog.sbccscript.plistの中身にある通り、1分に1回sbcc.rbを実行するようになります。
sbcc.rbの中では、buzztterやYahoo!から必要な情報を抽出して、/var/mobile/sbcc.txtにテキストとして書き出しています。
また、sbcc.rbは、buzztter等にアクセスに行く前に、sbcc_dummyconnectを実行しています。sbcc_dummyconnectを実行すると、FoundationのAPIを使って3Gがオンラインになります(圏外でなければ)。
3Gしかネットアクセスの手段が無い場所において3Gがオフラインである場合に、rubyからだと3Gをオンラインにすることができないため、このようなことをしています。

sbcc.rbの中身は以下のようなものです。

[cc lang=”ruby”]
#!/usr/bin/ruby
# -*- coding: utf-8 -*-
# テキストエディタEmacsでスクリプトを開いたときに
# エンコーディングをutf-8に自動設定するおまじない
# -*- coding: utf-8 -*-

# 文字列がUTF-8であることを宣言
$KCODE = ‘u’

# rssパースのライブラリを読み込み
require ‘rss/2.0’
# urlを、あたかもローカルにあるファイルであるかのように読めるように
require ‘open-uri’

# buztterのRSSから必要な文字列を抜いてくるメソッド定義
# 引数 numberofbuzz: 抜いてくるbuzzの数
# 引数 length: buzz一つ当たりの長さ。これを超える長さのbuzzは、その長さに切り取られる
def topbuzz(numberofbuzz, length)

# 例外処理用構文開始 begin 〜 rescue 〜 end
# http://www.namaraii.com/rubytips/?%CE%E3%B3%B0
begin
# buzztterのRSSを取得し、変数fhへ格納
fh = open(‘http://buzztter.com/ja/rss’)
# 取得したrssをRSSパーサでオブジェクト生成
# さらにRSSのアイテム一つ一つを配列として変数rssに格納
rss = RSS::Parser::parse(fh.read).items
# 出力となる文字列型の変数outputを初期化
output = “”
# RSSのアイテムが配列として格納された変数rssのアイテム数だけ繰り返し
# rss.eachにしないのは、頭から引数numberofbuzzで設定した数で繰り返しを止める都合から
# 何個目のアイテムであるかを把握する必要があるため
rss.each_index do |index|
# 配列である変数rssの当該個数目のアイテムを、引数lengthで切り詰めた上で
# 変数outputのお尻にくっつけていく
output += rss[index].title.gsub(/^(.{#{length}}).+/, “1”)
# 当該個数目が引数numberofbuzzで設定した個数だったら繰り返しを脱出
# numberofbuzz – 1となっているのは、indexが0から初まるため
if (index == numberofbuzz – 1) then
break
end
# 後にアイテムが続く場合は、変数outputのお尻に/をくっつける
output += “/”
end
# メソッドからの返り値として変数outputを渡す
return output
rescue
# エラーが生じたときは、例外を発生させて終了
# エラーは、RSS取得などで発生することが多いはず
# その場合に、sbcc.txtが空の文字列で上書きされないようにしている
raise “error occurred at topbuzz”
end
end

# Yahoo!ファイナンスの円ドル相場を抜いてくるメソッド
def usdjpy()
# 変数yenを空文字列で初期化
yen = “”
# 変数timeを空文字列で初期化
time = “”
# ターゲットとなるurlを変数urlに格納
url = ‘http://stocks.finance.yahoo.co.jp/stocks/detail/?code=USDJPY=X’
# 円ドル相場をターゲットurlから抜き出す正規表現
# に囲まれた「数字.数字」という文字列を取り出す
# 「d」で0から9の数字を意味する。「.」で任意の1字という特別な意味になるので
# その効果を打ち消すために「.」とバックスラッシュでエスケープしている
# 半角丸括弧に囲まれた部分がブロック構文の仮引数に配列として渡ってくる(後方参照)
# 正規表現は//で囲んで表現するので、その中に/が登場するとそこが正規表現の終了位置だとみなされてしまう
# 正規表現の終わりを意味しなようにをとバックスラッシュでエスケープしている
yen_regex = /(d+.d+)/
# 円ドル相場をターゲットurlから抜き出す正規表現
# yen_regexと同様。ページ中から抜き出したい特徴的な部分を探してくるとこうなる
# 全角の丸括弧に囲まれたのが抜き出し対象となる時刻
# 半角丸括弧でくくって、ブロック構文の仮引数に配列として渡るようにしている
time_regex = /”yjSt”>…((d+:d+))/
# 例外処理用構文開始 begin 〜 rescue 〜 end
# http://www.namaraii.com/rubytips/?%CE%E3%B3%B0
begin
# 指定のurlからページを取得し、変数bufに格納
buf = open(url).read
# 変数bufを正規表現を格納したyen_regexでスキャンしていく
# http://www.ruby-lang.org/ja/man/html/String.html#scan
# 取得したページがいつものフォーマットになっていれば、ブロック構文の仮引数mに
# 円ドル相場が配列として格納されているはずなので、その最初の要素を、
# フォーマットを適用するsprintf関数で「xx.xx円」といった
# 小数点第二桁までの形に整形して変数yenに格納
# yen_regexが一致(マッチ)しない場合は、yenは空白文字列となる
buf.scan(yen_regex) do |m|
yen = sprintf(“%.02f円”, m[0])
end
# 変数bufを、再度正規表現を格納したtime_regexでスキャンしていく
# http://www.ruby-lang.org/ja/man/html/String.html#scan
# 取得したページがいつものフォーマットになっていれば、ブロック構文の仮引数mに
# 当該円ドル相場の時刻が配列として格納されているはずなので、その最初の要素を、
# そのまま変数timeに格納
# time_regexが一致(マッチ)しない場合は、timeは空白文字列となる
buf.scan(time_regex) do |m|
time = m[0]
end
# yenが何らかの理由でnilだった場合は、ダミー文字「N/A」と差し換える(三項演算子)
yen = yen ? yen : “N/A”
# timeが何らかの理由でnilだった場合は、ダミー文字「N/A」と差し換える(三項演算子)
time = time ? time : “N/A”
# 取得したyenとtimeを「xx.xx円(00:00)」といった形に整形して返り値として渡す
return “#{yen}(#{time})”
rescue
# エラーが生じたときは、例外を発生させて終了
# エラーは、ページの取得などで発生することが多いはず
# その場合に、sbcc.txtが空の文字列で上書きされないようにしている
raise “error occurred at usdjpy”
end
end

# Yahoo!ファイナンスの日経平均株価を抜いてくるメソッド
def nikkeistockaverage()
# 変数nsaを空文字列で初期化
nsa = “”
# 変数timeを空文字列で初期化
time = “”
# 変数daybeforeを空文字列で初期化
daybefore = “”
# ターゲットとなるurlを変数urlに格納
url = ‘http://stocks.finance.yahoo.co.jp/stocks/detail/?code=998407.O’
# 日経平均株価をターゲットurlから抜き出す正規表現
# に囲まれた「数字,数字.数字」という文字列を取り出す
# 「d」で0から9の数字を意味する。「.」で任意の1字という特別な意味になるので
# その効果を打ち消すために「.」とバックスラッシュでエスケープしている
# 半角丸括弧に囲まれた部分がブロック構文の仮引数に配列として渡ってくる(後方参照)
# 正規表現は//で囲んで表現するので、その中に/が登場するとそこが正規表現の終了位置だとみなされてしまう
# 正規表現の終わりを意味しなようにをとバックスラッシュでエスケープしている
nsa_regex = /(d+,d+.d+)/
# 時刻をターゲットurlから抜き出す正規表現
# nsa_regexと同様。ページ中から抜き出したい特徴的な部分を探してくるとこうなる
# 全角の丸括弧に囲まれたのが抜き出し対象となる時刻
# 半角丸括弧でくくって、ブロック構文の仮引数に配列として渡るようにしている
time_regex = /”yjSt”>…((d+:d+))/
# 前日比をターゲットurlから抜き出す正規表現
daybefore_regex = /

(.?d+.d+)(.?d+.d+)%)

/
# 例外処理用構文開始 begin 〜 rescue 〜 end
# http://www.namaraii.com/rubytips/?%CE%E3%B3%B0
begin
# 指定のurlからページを取得し、変数bufに格納
buf = open(url).read
# 変数bufを正規表現を格納したnsa_regexでスキャンしていく
# http://www.ruby-lang.org/ja/man/html/String.html#scan
# 取得したページがいつものフォーマットになっていれば、ブロック構文の仮引数mに
# 日経平均株価が配列として格納されているはずなので、その最初の要素を、
# 「円」と結合して変数nsaに格納
# nsa_regexが一致(マッチ)しない場合は、nsaは空白文字列となる
buf.scan(nsa_regex) do |m|
nsa = m[0] + “円”
end
# 変数bufを、再度正規表現を格納したtime_regexでスキャンしていく
# http://www.ruby-lang.org/ja/man/html/String.html#scan
# 取得したページがいつものフォーマットになっていれば、ブロック構文の仮引数mに
# 時刻が配列として格納されているはずなので、その最初の要素を、
# そのまま変数timeに格納
# time_regexが一致(マッチ)しない場合は、timeは空白文字列となる
buf.scan(time_regex) do |m|
time = m[0]
end
# 変数bufを、再度正規表現を格納したdaybefore_regexでスキャンしていく
# http://www.ruby-lang.org/ja/man/html/String.html#scan
# 取得したページがいつものフォーマットになっていれば、ブロック構文の仮引数mに
# 前日比の数字が格納されているはずなので、その最初と二つ目の要素を加工しながら、
# そのまま変数daybeforeに格納
# daybefore_regexが一致(マッチ)しない場合は、timeは空白文字列となる
buf.scan(daybefore_regex) do |m|
daybefore = “#{m[0]}(#{m[1]}%)”
end
# daybeforeが何らかの理由でnilだった場合は、ダミー文字「N/A」と差し換える(三項演算子)
daybefore = daybefore ? daybefore : “N/A”
# nsaが何らかの理由でnilだった場合は、ダミー文字「N/A」と差し換える(三項演算子)
nsa = nsa ? nsa : “N/A”
# timeが何らかの理由でnilだった場合は、ダミー文字「N/A」と差し換える(三項演算子)
time = time ? time : “N/A”
# 取得したnsaとtimeを「xx,xx.xx円(00:00)」といった形に整形して返り値として渡す
return “#{nsa}(#{time})#{daybefore}”
rescue
# エラーが生じたときは、例外を発生させて終了
# エラーは、ページの取得などで発生することが多いはず
# その場合に、sbcc.txtが空の文字列で上書きされないようにしている
raise “error occurred at nikkeistockaverage”
end
end

# 渡された文字列をsbcc.txtに上書きで書き込むメソッド
def save(str)
fh = open(“/var/mobile/sbcc.txt”, “w”)
fh.puts str
fh.close
end

# ここまでメソッド定義
# ——————————–
# ここから、スクリプトが実行されたときに実行される内容

# /usr/bin/sbcc_dummyconnectを実行
# 3Gがオフラインだった場合にオンラインにする
# Wi-Fiがオンラインだった場合は特に効果は無し
system(‘/usr/bin/sbcc_dummyconnect’)

# 例外処理用構文開始 begin 〜 rescue 〜 end
# http://www.namaraii.com/rubytips/?%CE%E3%B3%B0
begin
# topbuzzメソッド、usdjpyメソッド、nikkeistockaverageを実行し、取得した文字列を空白を挟んで結合
# 変数outputに格納
output = topbuzz(3, 10) + ” ” + usdjpy + ” ” + nikkeistockaverage
# puts(output)
# saveメソッドで変数outputの中身をsbcc.txtに保存
save(output)
rescue
# 例外が出たときは何もしない
end
[/cc]

topbuzz(numberofbuzz, length)がbuzztterからTop Buzz Wordを抜いてくるメソッド、usdjpyがYahoo!ファイナンスからドル円相場を抜いてくるメソッドです。topbuzzは引数を二つ取ります。最初の引数はBuzz Wordをいくつ抜いてくるか。2番目の引数は、Buzz Word一つ当たりの長さ制限です。「topbuzz(3, 10) 」だとBuzz Wordを三つ抜いてきて、一つ当たり10文字までという制限を付けていることになります。

カスタマイズ

つまるところ、1分に1回の更新でよければ、SBCCScriptをインストール後、/usr/bin/sbcc.rbの中身をいじくればいいわけです。
好きなものをStatusBarCustomClockに表示して楽しんでください。

私、moyashiの現在までの活動を評価してくださる方は、ぜひ支援をお願い致します。


 - iPad, Jailbreak, ガジェット