2008-07-01
目次
りんご味Ruby 第27回 藤本 尚邦
今回は YahooHonyaku#open_top_page を実装します。
open_top_page は、第25回で書いた手順のうち「WebブラウザでYahoo!翻訳のページを開く」に相当します、以下のような手順:
・HTTPのGETメソッドでYahoo!翻訳のトップページを取得
・結果のHTMLをパースして必要な情報を取り出す
・成功したら、@top_page_opened に true をセットする
になります。
■ Ruby で HTTP GET するには
◇ その1 — 低レベルな方法 (socketをたたく)
Rubyで、HTTPプロトコルを扱う方法はいろいろ考えられます。もっとも原始的な方法は、TCPSocketを使って自分でHTTPプロトコルの通信をプログラミングすることでしょう。Yahoo!翻訳のトップページをHTTPでGETする場合は以下のようになります:
require 'socket'
response = TCPSocket.open("honyaku.yahoo.co.jp", 80) { |io|
io.write "GET / HTTP/1.1\r\n"
io.write "Host: honyaku.yahoo.co.jp\r\n"
io.write "User-Agent: Mozilla/5.0\r\n"
io.write "Accept-Charset: UTF-8\r\n"
io.write "\r\n"
io.read
}
html = response.split("\r\n\r\n")[1..-1].join # http body を取り出す
【編集部注:\r\n部分の『円記号』は『バックスラッシュ』に置き換えてください。以下も同様です】
TCPSocketクラスはファイルなどの入出力を扱うIOクラスの派生クラスです。io.write で HTTPリクエストを送信して、io.read でHTTPレスポンスを受信しています。response はサーバから受信した生データ(バイト列)ですから、最後の行では、(安直な方法で)HTTPレスポンスのボディ部分にあるHTMLを取り出しています。
・生バイト列を「連続した改行」で分割し配列を作る — split(“\r\n\r\n”)
・配列の最初の要素(HTTPヘッダ部)を取り除く – [1..-1]
・配列の残りの部分をつなげるとそれがHTTPボディ – join
(効率的にも、HTTPプロトコルの扱い方としても、最終的な実装としてはおすすめできませんが、まずは、とりあえず動くものを手軽に実装ということならばこういうのもありでしょう)
◇ その2 — 高レベルな方法 (net/http を使う)
上のようにTCPSocketの使い方自体は簡単ですが、HTTPプロトコルの面倒は自分で見なければなりませんでした。そこで、HTTPなどよく使われるプロトコルにはあらかじめライブラリが用意されています。/usr/lib/ruby/1.8/net の中を見ると、どんなプロトコルのライブラリがあるか見ることができます。HTTPについてはnet/http があります。以下はnet/httpの使用例です:
require 'net/http'
html = Net::HTTP.start("honyaku.yahoo.co.jp") { |http|
response = http.get("/", "User-Agent" => "Mozilla/5.0",
"Accept-Charset" => "UTF-8")
if response.is_a? Net::HTTPSuccess
response.body
else
raise "エラー発生!!"
end
}
もちろん、この response は生データではなく、Net::HTTPResponseクラスのオブジェクトとして構造化されていますから、リターンコードやボディ部などへのアクセスは簡単にできます。
◇ その3 — もっと高レベルな方法 (open-uri を使う)
net/httpではHTTPプロトコルの細かい機能をいろいろと使い込むことができますが、WebサイトのトップページのHTMLをGETするだけというような単純な用途にはおおげさすぎます。そういうときには open-uri を使います。
require 'open-uri'
html = open("http://honyaku.yahoo.co.jp/",
"User-Agent" => "Mozilla/5.0",
"Accept-Charset" => "UTF-8") { |io| io.read }
これでだいぶすっきりとしました。以上で、Yahoo!翻訳トップページのHTMLを取得することができるようになりました。
■ おまけ — 日本Ruby会議2008
6月20日(金)から22日(日)にかけて、つくば国際会議場で、日本Ruby会議2008が開催されました。立派な会議場で海外からの発表者も多く、Rubyに関して古代人(Rubyについての最初の本「オブジェクト指向スクリプト言語Ruby」出版以前からの人は古代人だそうです)の私には「ミカン箱の上で歌ってるときから応援してたアイドルが武道館でライブ」のような感慨深いものがあります。
Ruby会議で私が気に入っているものの一つに、発表中サブスクリーンに表示される IRC チャットがあります。とりわけ、海外の発表者のセッションのときには、逐一翻訳してくれるので、英語聞き取りが苦手な私にはとてもありがたいです。日本人の質問者が、(無理して)英語で質問しようとしてしどろもどろになると「日本語でおk」と突っ込まれ、さらに母国語がフランス語の発表者が英語で答えようとしてしどろもどろになると「フランス語でおK」と突っ込まれる、といったお約束を楽しみつつ、発表に関する解説があったりして素晴らしい。
Macに関しては、Laurent Sansonettiさん(Apple)による「RubyとMac OS Xの未来」という発表で、MacRubyを中心にした話がありました。MacRubyが目指すスローガンは:
Rubyを使う楽しみのためにパフォーマンスを犠牲にすることなく、成熟した Mac OS Xアプリケーションの作成を可能にする
で、高速化やスレッド安全性などが重視されています。「AppleはRubyによるMac OS X開発をサポートし推奨する(Apple supports and encourages Mac OS Xdevelopment using Ruby)」とのことです。これも楽しみですね。
◇ [補足] MacRubyのインストール方法(例)
$ svn co http://svn.macosforge.org/repository/ruby/MacRuby/trunk \
/tmp/macruby
$ cd /tmp/macruby
$ rake
$ sudo rake install
これで、/Library/Frameworks/MacRuby.framework および /usr/local 以下にインストールされます。MacRubyは、既存のRubyやRubyCocoaから完全に独立していて、それらを破壊することはありません(そのはずです)。なお、開発中につき、ビルドできなかったり動作しなかったりということはあるかもしれません。
次回は、HTMLをパースして翻訳リクエストのパラメータ名などの情報を取得します。今回のRuby会議で存在を知ったMechanizeというライブラリが、この目的に合うかもしれないので、試してみようかと考えてます。
藤本裕之のプログラミング夜話 #140
WWDCのために時間が開いてしまったが、話がどこまで行ったか覚えてますか? そう、パソコンを買うとバンドルソフトというものがたくさん付属してくるようになり、ほとんどのユーザはバンドル品以外のソフトをわざわざ購入しなくなる。早い話ワープロならワープロ、辞書なら辞書、一つの分野で一つの製品がバンドル品に選ばれてしまうと競合品が生き残るのはとっても難しい状況……なんてんですか、1匹の精子が受精すると他の何億が即座に御陀仏てな「やけっぱちのマリア」的というか、そんな話になったわけ。
この状況下でソフト屋が生き残るミチは2つ。競合製品のいない独自分野のソフトを生み出すか、それとも競合製品に勝ってバンドルの座を勝ち取るか。前者は聞けば格好いいけど早い話それは冒険なわけだし、既になんらかの製品をもってるのであれば当然後者を目指す。前回見たようにバンドルソフトには「おまけ商品と見なされてしまう」というデメリットも確かにあるのだが、それでも知名度が上がることはいいことだし、流通を通さずにユーザから直接支払いを受けられるバージョンアップは美味しいし、と。
ところがあのバブル弾けて10年、2000年問題を乗り越えてやってきた21世紀はそんな甘い時代ではなかったのである。……って実のところ、そういう時代が来てしまえば誰が見ても当たり前のような気がしたんだけどね。要するにインターネット・ブームに乗って増加したパソコンユーザってのは、かつてビル・ゲイツが夢想したように「一家に一台、家電のようにパソコンを買って」
くれたけど、その使い方も「家電のよう」だったのだ。こっちはさすがのビル・ゲイツでも予想外(たぶん)、世界最高のビジネスマンでさえ予想しないことをオレたちシモジモのプログラマ風情が予想できるはずもなかった。
え? 「パソコンの使い方が家電のよう」ってどういうことだって? わかりませんか? つまり冷蔵庫や洗濯機、電子レンジと同じ、普通のヒトは一度買ったら、壊れでもしない限りもうその機械に金をかけたりしないのである。……例えば冷蔵庫の目的はモノを冷やすことだ。したがってユーザは冷蔵庫が冷えてる限り不満はない。洗濯機の仕事は洗うこと、そりゃ「こっちの方がよ
く落ちる」とか「これを使えば森の香り」とか言われれば洗剤や柔軟剤は変える。でも洗剤や柔軟剤は誰がどう見ても消耗品だからね。電子レンジにしてもそうでしょ? そういうものと比べるからいけない? もっとパソコンに似た使われ方をするものがあるだろって?
21世紀初頭、すなわち2001年(21世紀は2001年から、2000年からだと思ってませんでした?)の日本における一般的家庭において、おそらくパソコンとその使用形態が最も似通った家電はビデオデッキであったと思う(DVDプレイヤーぢゃないのか、と言うかも知れぬが、社団法人 日本映像ソフト協会の資料によればDVD再生機器の推定普及率は2002年で35%なので、その2年前であれば圧倒的にビデオデッキを使っている家庭の方が多かったはず)。そこで考えて欲しいのだが、普通の家庭におけるビデオデッキ関連の支出で最も多いのはどんな項目だろうか? 生テープを買う? 違うよ、ビデオのレンタル料金である。
どういうわけか我々の業界のニンゲンにはあのビデオデッキという機械を「何かを録画してとっておく機械」と認識しているヒトが多いのだが、普通の家庭ではあれは概ね「映画を借りてきて観るため」の機械だったのだ。そりゃたまには外出のために観られない番組を録画してあとで観たりするために生テープも買うさ。でも一度観たら消してまた他のを録画するために使う。ナニを言いたいかというと、こないだついに死刑になったミヤザキツトムみたいにアニメだのなんだの録画して部屋いっぱいに貯め込んでいるってヒトは、昔もイマも……いかにあんたの周りに多かろうと、世間一般を分母としたら圧倒的少数派なのである。
パソコンもこれと同じ事情なんでね、こいつをメシの種として、四六時中その前に座っている我々は、なんとなく「パソコンがもっと普及したらすべてのユーザが我々と同じようなパソコンの使い方をするに違いない」という幻想を持っていたのだ。別に現状に不満がなくても新しいOSやソフトが出ればバージョンアップし、お金を使ってくれるというような、ね。でもそれは大間違い
だった。彼らはバンドルソフトをおまけ商品と認識した上に、そのおまけ商品以上のものを欲しがらなかったのである。
(以下次回 2008_06_26)
高橋真人の「プログラミング指南」第138回
〜XcodeによるPowerPlant X入門(27)〜
こんにちは、高橋真人です。
今年もWWDCに参加してきました。時代の流れとは言え、ついに今年はCarbonの名の付くセッションが一つもありませんでした。あのアドビ社ですら、Mac用アプリケーションのCocoaへのポーティングを開始した今、もはやCarbonにこだわっている場合ではないのかもしれません。
まあ、私としてもCarbonに固執しているわけでもありません(最近、Carbonで書くアプリケーションはこの連載用のプログラムだけになってしまいました・笑)ので、PowerPlant Xの連載にもそろそろ見切りを付けようかな、と思い始めています。
ともあれ、やりかけた話には決着を付けねばなりません。いよいよ、HIViewのカスタマイズのハイライト(というほど凝ったことはしていませんが)ということで、今までやってきたシステムが提供するPushButtonコントロールをそのまま利用するのではなく、表示部分や内部動作などを自前で実装する形にしてみたいと思います。(もちろん、OSの力を借りながら、ですが)
では早速、プロジェクトの準備から。前のプロジェクトを複製してPPxForXcode09を作ってください。そして、MyView.cpの描画部の実装コードを以下に置き換えます。
OSStatus
MyView::DoControlDraw(
PPx::SysCarbonEvent& ioEvent,
ControlRef inControl,
ControlPartCode inPartCode,
RgnHandle inClipRgn,
CGContextRef inContext)
{
#pragma unused (ioEvent, inPartCode, inClipRgn)
HIRect frame;
GetLocalFrame(frame);
HIThemeButtonDrawInfo buttonInfo = {
0, kThemeStateActive, kThemePushButtonNormal,
kThemeButtonOn, kThemeAdornmentNoShadow
};
if (::IsControlHilited(inControl) and ::IsControlActive(inControl)) {
buttonInfo.state = kThemeStatePressed;
}
HIRect labelRect;
HIThemeDrawButton(
&frame, &buttonInfo, inContext,
kHIThemeOrientationNormal, &labelRect);
HIThemeTextInfo textInfo = {
0, kThemeStateActive, kThemePushButtonFont,
kHIThemeTextHorizontalFlushCenter,
kHIThemeTextVerticalFlushCenter, kHIThemeTextBoxOptionNone,
kHIThemeTextTruncationMiddle, 1, true
};
HIThemeDrawTextBox(
CFSTR("Button"), &labelRect, &textInfo,
inContext, kHIThemeOrientationNormal);
return noErr;
}
モサ伝の制限上、横の文字数が限られるために行数が多くなってしまっていますが、空白行を除けば10行余りのコードです。
ただ今回のコードは、ある程度Carbonで凝ったアプリケーションを書いた経験のある人でないと見慣れないものばかりかもしれません。特に目立つのは”HITheme…”という識別子です。これは、昔懐かしい(?)アピアランスマネージャの流れを汲む仕組みに属するものです。
アピアランスマネージャと言われてもピンと来ない人も最近はいるかもしれませんので、少し説明します。かつてまだMac OS 8も出ていないころ、OSが標準で提供するUIパーツは今のものに比べずっとシンプルでした。開発者がもっと多彩なUIを作りたいと思うと、OSが使用している仕組みを流用するなどということもできず、それこそ一から実装をする必要があったために、かなりの作業量を要したのです。
新世代のOSを模索していたアップルが、そういう状況を解決しようとして出てきたのがアピアランスマネージャ、そして“テーマ”という考え方です。例えば“選択”を行った時に、その選択されているという状態をどのように表現するかということを考えてみます。
今のMac OSでは、選択状態を表す色はデフォルトでは水色になっています。では、自分で独自のUIパーツを作った時に選択色を水色にすればいいのかというとそうではないわけです。何故なら、この“水色”をユーザーが変えることができるようになっているからです。
システム環境設定のアピアランスというところを選ぶと、「強調表示色」というポップアップボタンが見えると思います。試しにこれを変えてみると、その後、テキスト選択やリスト選択などはすべて新しい色で描かれることが分かるはずです。
このように、例えば選択色を描く際に“水色”と決め打ちをするのではなく、システムに対して「テキストの選択状態を示す色は?」などと逐一問い合わせをして、その色で然るべき部分を描くのがアピアランスマネージャの仕組みに乗っ取ったやり方です。
ただ、前述の「強調表示色」の変更だけでは、メニューなどのハイライト表示などは変わりません。一応、アピアランスのシステム環境設定には名も「アピアランス」というポップアップがあり、ここをデフォルトの「ブルー」から「グラファイト」に切り替えることでメニューなどの色を変えることはできるのですが…
実は、かつてアピアランスマネージャが登場したころ、アピアランスのテーマには”High Tech”と”Gizmo”という名の派手なテーマも存在していました。特に”Gizmo”の方は見た目がカラフルで、操作をするといろいろなギミック音を発するという凝ったものでした。
当初は、さらにデベロッパによって様々なテーマが作られて、ユーザーがそれらを好き勝手に選んで使えるといった構想もあったのですが、一時フリーウエアでいくつかのテーマもあったものの、今ではそういった考え方自体が衰退してしまったように見えます。
HITheme…の先頭のHIは、「ヒューマン・インターフェース」の略ですが、これはCarbonの技術のカテゴリーということになっているため、いずれはこのテーマという発想自体もなくなってしまうのかもしれません。
とりあえず、プログラムを走らせてみれば動きは確認できるでしょう。コードの中身に関しては、Carbonフレームワークの奥深くにしまわれているAppearance.hとHITheme.hというヘッダファイルをご覧になれば、理解できると思います。
◇MOSAからのお知らせと編集後記は割愛します◇