2008-07-15
目次
りんご味Ruby 第28回 藤本 尚邦
引き続き YahooHonyaku#open_top_page を実装します。前回は、ヤフー翻訳のトップページのHTMLを取得するための HTTP GET について、様々なレベルの手段を示しました。今回は、取得したHTMLをパースして、翻訳リクエストのためのフォームからパラメータ名などの情報を取得します。
まず、YahooHonyaku#open_top_page のコードを示します。
def open_top_page
require 'open-uri'
url = "http://honyaku.yahoo.co.jp/"
http_header = {
"User-Agent" => "Mozilla/5.0",
"Accept-Charset" => "UTF-8"
}
html = open(url, http_header) { |io| io.read }
parse_form!(html)
@top_page_opened = true
end
ヤフー翻訳は、HTTPヘッダーでUser-Agentを明示しないとちゃんと機能しないようなので、Accept-Charsetとともにopen-uriのopenメソッドに引数として渡します。(まだ実装も定義もしていない)parse_form!で、htmlをパースして翻訳リクエストのフォームからパラメタなどの情報を取得します。最後に、@top_page_opened に真偽値の true をセットします。
■ HTMLのパース
HTMLをパースしてデータにアクセスする方法にも、HTTP GETの場合と同様、さまざまな手段が考えられます:
・正規表現を使ってやっつけでデータを取り出す
・HTMLをまじめにパースする
・既存のHTMLパーサを使う
この中から、手軽でかつ確実な手段として、HTMLパーサのひとつであるHpricot を使って実装することにします(他の手段はたいへんなので省略します)。
◇ Hpricotの確認
Hpricot は、Leopard に最初からインストールされています…と言い切りたいところなのですが、本当にそうだったかどうか忘れてしまいました。ターミナルで:
$ ruby -r rubygems -e "require 'hpricot'"
を実行して、エラーメッセージ(LoadError)が表示されなければ、すでにインストールされています。いずれにせよ
$ sudo gem install hpricot
を実行することにより、最新のhpricotをインストールまたはアップデートすることができます。
◇ parse_form! の実装
parse_form! の実装は以下の通りです(注 – 要点を見やすくするためエラーの処理はいいかげんになっています):
def parse_form!(html)
require 'rubygems'
require 'hpricot'
doc = Hpricot(html)
@form = doc.search("form[@name=textFormEntry]")[0]
@key = @form.search("input[@name=key]")[0]["value"]
@time = @form.search("input[@name=time]")[0]["value"]
if @form.nil? or @key.nil? or @time.nil?
raise "Yahoo翻訳の返すHTMLのパースに失敗しました"
end
end
HpricotメソッドにHTML文字列を渡して呼ぶと、HTMLをパースして結果をHpricot::Docオブジェクトとして返します。Hpricot::Doc#search は、HTML構文木の中で、Xpath または CSS バターンにマッチする要素を検索します。textFormEntry という名前の form要素を探して、その中の2つのinput要素(それぞれの名前はkeyとtime)の値をインスタンス変数(それぞれ@keyと@time)に代入しています。これらのインスタンス変数の値は、翻訳リクエスト(HTTPPOST)を作るときのバラメータとして使います。
Hpricot::Docオブジェクトには、searchを始めとしてドキュメント内の要素や属性などにアクセスするためのメソッドがいろいろと用意されています。Hpricotの使い方に興味のある方は、ドキュメントが:
file:///usr/lib/ruby/gems/1.8/doc/hpricot-0.6/rdoc/index.html
にインストールされているはずなので、この中のREADMEを読みながら、irbなどでサンプルコードを試してみると良いでしょう。
■ Mechanizeは?
ところで、前回、Mechanize というライブラリがなんだか便利そうだぞ、試してみたい、というようなことを書きました。実際、今回の記事で紹介しようと思って試してみたのですが、衝撃的(?)な事実が発覚。なんと、今まで、ちまちまと作ってきた、あるいはこれから作るつもりの HTTPプロトコル・HTMLのパース・Webブラウザとしての振舞いのプログラミングのほとんどが、超お手軽にプログラムできてしまったのでした。
このお手軽さ・便利さはとてもRuby的だと思うので、今すぐにでも紹介したいところなのですが、せっかくここまでYahooHonyakuの実装の説明を続けてきたのですから、Mechanize なしでとりあえず完成させてから紹介しようと思います。
藤本裕之のプログラミング夜話 #141
さて前回どこまで行ったかというと、ユーザ……というより話の流れからは「パソコン購買者」という呼び名のほうが正確だと思うが、は確かに増えたものの、その多くが「買ったままの状態」に満足し、新たにソフトを買い足すどころかバンドルソフトのバージョンアップもしてくれない。こりゃまたどういうわけだ、世の中間違っとるよぉ♪と思うかも知れないが実のところ間違って
いたのはオレタチの方であったんである誠に遺憾に存じます、と……この辺でしたかね。
もちろん異論もある。確かにビデオデッキの(あ、突然どうしてビデオデッキが出てきたんだ? と思った人は前回分を参照のこと)用途の主流は録画してテープを保存ぢゃなくて、レンタルビデオの再生だったかも知れんけど、CDとかはどーよ、買ってうちに貯めるんとちがうの? と思った人もいるのではないか。
いやそーだと思うよね、現在約1,000枚の音楽CDの整理がつかず、まったくどうしていつの間にこんなに増えてしまったのかとため息をついているオレはその意見に深く激しく同意するモノであります。普通そうだよね? え、1,000枚が普通か? まぁ1,000枚は普通よかちと多めかもしれないけどさぁ。
ところが先日、ワタシはそういう自分の常識というか依って立つ足場というか、が、ズズズズズリっと音を立てて動くようなパラダイムシフト的話を知ったのである。
この前……6月の23日にアップルから、iTunes Store からの楽曲のダウンロードが全世界で累計50億曲を超えたというニュースが流れた。50億と言ったら50億である、アップルはこのうちどんだけが日本での売り上げなのか明らかにしてないが、まぁ1億や2億はありそうでしょ? となれば、デジタル音楽配信というさぞかし iTunes Storeが重きを占めている……と思うでしょ?
ところが調べてみると驚愕の事実がわかるのだ。
ここ(http://www.riaj.or.jp/release/2008/pr080221.html)に社団法人日本レコード協会が発表した2007年の有料音楽配信売上実績ちう表があるのだが、これによれば2007年に利用された有料音楽配信の総回数は464,996,000回……ざっと4億6千万回。で、そのうち iTunesを含むインターネットを通してのダウンロードはなんと、30,983,000回。1割に満たないのである。金額ベースでやっと7.8%である。
残りの9割以上を占めている有料音楽配信とはなにか? ここでみのもんた風にもったいぶってもしょうがないので答えを書くとこれは「モバイル」なんである。つまりケータイに対してダウンロードされる着うた、着うたフルの類ですな。考えてみれば iPodがいくら売れているといっても携帯の比ではないわけで、パイがでかいんだから9割超が着うたなのも当然か、とも思ったのだが、これ、パイの大きさだけでわかったつもりになっていい話ではないのだ。
オレと同じように不案内な人もいると思うので解説すると、着うたというのは iTunes Storeで売ってるような音楽デジタルデータの一部(サビの部分とか)をケータイの着信音として利用できるサービスで、1曲平均105円でダウンロードできるもの。これが iTunes Storeと同じまるまる1曲になったのが着うたフルなんだが、ビットレートが32Kbps〜48Kbps(iTunes Storeで売られてるのはm4pが128kbps、m4aなら256kbpsである)と低音質にも関わらず値段は1曲210円〜420円もする。
まぁしかし値段は置こう、iTunes Storeで買うほうが音質も良くて安いとしても、前提となるパソコンやiPodはそれなりに高価だし(今度 iPhoneで可能になるだろうが)、ひょいと着信音にできるわけぢゃない。オレがパラダイムシフト的と言ったのは、こうして売れている着うたが「他のメディアに保存できない」ってことなのだ。つまりね、例えば420円で宇多田ヒカルの新曲を着
うたとして買うでしょ? 他の曲を着うたにするときには(まぁ何曲かはストックできるようだが)基本的にそれは消しちゃうのである。
オレ的な感覚だと「買ったものなんだからCDとかに焼いておき、将来好きなときにいつでも楽しめる」のが普通とか思うのだが、現実は違うのである。やぁびっくりしました。ケータイで宇多田の「Stay Gold」を着うたにしているお姉ちゃんはあれをほぼレンタルビデオ(2008年ではDVDですな)感覚で「消費」しているんだよ。ほんで、そういう感覚なんだとわかってみると、他のコトも見えてくるような気がするのである。 (以下次回 2008_07_12)
高橋真人の「プログラミング指南」第139回
〜XcodeによるPowerPlant X入門(28)〜
こんにちは、高橋真人です。
朝のニュースワイドショー番組で、午前7時のSoftbankショップ表参道店からの生中継が、しかもほとんどのテレビ局で同時に行われるなどという、今までの私たちにはほとんど縁のなかった「メジャー」な世界での出来事に興奮し、戸惑い、何だか訳が分からなくなりそうな今日このごろですが、皆さんは元気にiPhoneプログラムを開発されておいででしょうか?
私はと言えば、SDKの登録作業でひっかかり、わざわざUSにまで行ったにも関わらずWWDCの会場でも解決せず、結局、帰国後にデベロッパサポートとメールのやり取りやらFAX送信やらでようやく開通したものの、実機への転送作業に苦心惨憺の末成功したのが、ようやくiPhone 3G発売日の前日(涙)。
とりあえずiPhoneアプリの構想はあるものの(今はアイデアが勝負ですから、どんなアプリかは発表するまでは内緒・笑)、販売に行き着くまでの手続きがまたかなりややこしいという噂を聞いて恐れおののいている状態です。
「こんな時にPPxの連載なんかやっている場合かよ」というご批判の声があるのは重々承知ですが(笑)、実はiPhoneプログラムにも(無理矢理?)PPxを活用することはできるのではないかと踏んでいますので、批判もモノともせず(笑)、もう少し続けてまいります。
さて、前回作成したプログラムには実は足りない部分がありました。この連載をしっかり読んでくださっている方は、こちらから言う出すまでもなくお気付きかもしれませんが。
一つ前のプログラムでやった「ボタンがディスエーブルになった時の描画処理」がこのプログラムには欠けています。ウインドウを2つ以上開けば、いやでもどちらかのウインドウは後ろに回りますから、ボタンだけがアクティブなままだと、ちょっと浮いて見えてしまいます。
それを防ぐためには、ディスエーブルになったときの見た目を自分自身で描画してやる必要があります。以前の、ボタンコントロールを流用してViewのビジュアルを得ていた時には、実はボタンコントロール自体が、自分がディスエーブルになったことを察知してちゃんとこの処理をやってくれていたのですが、自分ですべてをやる場合は、そこも自分で面倒を見てやる必要があります。
本当は、前回のときにこの部分の実装も組み込んだ状態でご紹介したかったのですが、ボタンそのものに関してはすぐにできたものの、表示文字列をディスエーブル状態にする方法がなかなか見つからず、間に合いませんでした。
では、早速コードをごらんいただきます。例によって、DoControlDraw()内のみの変更です。
変更箇所は以下の2つです。
・ハイライト状態の判断部分に3行追加します。
【旧】
if (::IsControlHilited(inControl) and ::IsControlActive(inControl)) {
buttonInfo.state = kThemeStatePressed;
}
【新】
if (::IsControlHilited(inControl) and ::IsControlActive(inControl)) {
buttonInfo.state = kThemeStatePressed;
}
else if (not ::IsControlActive(inControl)) { // ここからの3行を追加
buttonInfo.state = kThemeStateInactive;
}
・HIThemeDrawTextBox()の直前に以下を挿入します。
if (not ::IsControlActive(inControl)) {
textInfo.state = kThemeStateInactive;
RGBColor textColor;
::GetThemeTextColor(
kThemeTextColorPushButtonInactive, 32, true, &textColor);
::CGContextSetRGBFillColor(
inContext,
(float)textColor.red / 65535,
(float)textColor.green / 65535,
(float)textColor.blue / 65535,
1.0);
}
以上を変更して走らせてみてください。
ウインドウが後ろに回った時に、ボタンの部分が”Button”というラベルも含めて薄く表示されるようになったことが分かると思います。
前回から登場しているHIThemeTextInfoというもの自体、今回のように自分で独自の“見た目”を持ったViewやウインドウを作ることでもなければ、めったに関わることはない仕組みだと思いますが、単に表示を薄くするだけでも、今回ご覧いただいたように決して簡単ではありません。
まあ、前回お話ししたアピアランスマネージャが、ユーザーサイドに大幅に自由を提供しようという設計方針だったために、いちいちシステムに対して「Pushボタンのアクティブでない時の描画色は何色?」と問い合わせをして色をもらい、それで自分で設定してから文字を描くという回りくどい手順になっているわけです。
とかく、「Cocoaなら、ずっと簡単にできるのでは?」と思われる方はいらっしゃるのですが、内部的に行っていることには実はそんなに大きな違いはありません。あとは、「気軽に使えるがカスタマイズの自由度には妥協する」か、「カスタマイズは徹底的に自分の気の済むようにやりたいので、多少の複雑さは甘んじて受け入れる」かの選択になるのだと思います。
どちらが正しいのか、という性質の問題ではなく、必要に応じてどちらの選択肢も選べるというのが、いいのだと思います。
◇MOSAからのお知らせと編集後記は割愛します◇