1.プログラム プログラム名: 君ならどう書く? (ウェブアプリケーション) 発表者名: Perl: 早川真也(エッジ) Python: 浦郷圭介(日本Pythonユーザ会) Ruby: ただただし(tDiary) PHP: 重松修 記録者名: 波田野裕一 2.時間 開始時刻: 15:30 終了時刻: 16:00 (質疑応答: 15:55 〜 16:00) 3.発表の概要、論点 お題: WebサイトからRSSファイルを取得し、それをブラウザで閲覧する Webアプリケーションを作成する。 RSS * Webサイトの概要や更新状況などを、 配布用にコンパクトに記述するフォーマット * XML、行指向などいくつかのフォーマットがある。今回はどちらでも良い。 作成のポイント * HTML埋め込み画面生成(ループ、HTML用文字列整形)が主題 * RSSファイルの入手方法は重要でない * XMLでなく行指向のRSS/3.0フォーマット対応でもOK 4.発表の流れ、内容 ○Perl ・Perl で CGI とか Perl で webアプリケーション みんなすごくいやな顔されると思うが、いろいろな書き方がある。 今回 webアプリケーションを自分はこう書いてみた。 use strict はもちろん、 ?withCGI ?LWP simple テンプレート というモジュールを使っている。 クエリを生成して、ヘッダを text/html で、そのセットを UTF8 で出力している。 次にテンプレートモジュールを生成して、テンプレートの内容はデータから取って、それの引数に ?LWP で取ってきた /. のRDFの内容を渡している。 HTMLのテンプレートの内容 RSSの解析はテンプレートモジュールの標準のプラグインにある ?XML&SSL というプラグインを使用している。 ここでは、foreach で ニュースのアイテムをループで回して出力している。 これを見る限りすごいおぞましいとは感じなかった。 ・テンプレートモジュールとは テンプレートツールキットと呼ばれている。 非常に強力なモジュールで、テンプレートの中にもう一つの言語があるような感じ。 すごい色々な事ができる。 ・動作デモ 時間の都合で省略。(実際には忘れてしまっただけ) ・CPAN CPANモジュールがいかに大事なものかわかってもらえればいい。 CPAN があるから Perl を使っている人もいると思う。 (CPAN の発音について) ・XMLに関するCPANモジュール XML::RSS::Parser などが一般的。 テンプレートツールキットなどのプラグインでも ?HTML::RSS内(?)モジュール を使っている。 XML::RSS::Tools SSLを使って高度な処理をする。 XML::RSSLite 文字列で渡してハッシュで受け取るなど、単純なことをしたい時に使える。 他にもたくさんモジュールがある。 /. からRDFを取ってくるところで ?LWP を使っていたが webオートメーションに関するCPANモジュールは HTTP:: WWW:: などがある。 ・webアプリケーションを作るフレームワーク CGIアプリケーションなどがあるようだ。 MLが活発で使っている人も多いらしい。 自社でも スケッチ(?) というフレームワークがある。 ・inline.pm inline Ruby、inline Python などがあるので、この後解説されるコードもたぶん Perl の中で動くと思う。 inline PHP はあるかどうかわからない。 ・三種の神器 inline C ?Bジェネレート ?フィルタシンク この3つのモジュールで Perl の世界がかわる。 これがあれば何でもできる。 ○Python このサンプルはわざわざ SAX を使っている。 RSS はツリー状の XMLフォーマットだが、DOM をつかわず、SAX を使ってツリーとして見ないようにしている。 SAX はイベントハンドラなので、これを使ってかたまりを認識するという方式を使っている。 (発表者注) SAX ではタグとテキストを別々に認識しながら進みます。 データの認識するエレメントの名前などを羅列して書いて、それをあとで使うデータとして入れてある。 RSS3 という XML でなく Ruby の YAML のフォーマットに近いやつを使うルーチン(72〜97行目)を使う。 キモはCGIの部分で、rssget.cgi の 34行目で render_html() でだいたいの処理して出力している。 render_html() という関数は同じ CGI にあって、parse_rss()(30行目) で RSSFILE_URL をひろって開くと RSSファイルを開いて処理して表示する。 ・動作デモ 出力結果 一番最初がヘッダーのデータで、ディスクリプションなどが書いてある。 RSSで出てるやつの分だけ表示される。 ・エンコードのコーデック rssget.py 25行目 ENCODING = 'UTF-8' (資料) (本番 では EUC-jp) 出力するときのエンコーディングを決めてるだけ。 入力側 XMLファイルでエンコーディング指定されている。 これをデコードの情報として使って UTF8 だと認識して変換している。 出力側 好きなコーデックで出力できる。 ○Ruby (標題) 'Ruby による RSSビューア... を装った新添付ライブラリの宣伝' ・ライブラリの数 Rubyの最大の弱点と言われてきた。 他の言語に比べてライブラリが非常に少ない。 今回出た1.8では、標準ライブラリ、添付ライブラリが強化された。 ・添付ライブラリ フリーソフトウェアの初期に配布には重要。 どこかからライブラリ入れないと動かないと、それだけで気分が萎えてしまう。 Ruby にも RSSライブラリが RAA に 何種類か登録されているが、今回はあえて添付ライブラリだけで作ってみた。 ・ポイントは3つ 1. /.の RSS を取ってくるので、HTTPクライアントである必要がある。 1.6 からある net/http を使う。 プロクシの環境変数の有無にかかわらず get_rss() というメソッドでは、一つの呼び方でできるようになっている。 HTTPの Proxy というクラスが プロクシの設定の有無のどちらでも同じ挙動をしてくれる。 2. 持ってきたRSSファイルが XML なので解析しなくてはいけない。 1.8 で追加になった REXML を使う。 初めて使ってみたので、あまり突っこまないように。 DOM でも SAX でもない独自のインスタンスを持っている。 Ruby的にわかりやすい使い方になっている。 チャンネルとアイテムのリストを数え上げるイテレータの定義をしている。(次の ERB で効いてくる。) テンプレートの中で、each_channel や each_item を使うことでテンプレートの部分がかなりすっきりする。 3. 解析した結果を CGI として実行して HTML として展開する。 従来からある cgi.rb に加えて、ERB を使う。 これからの CGI は、テンプレートを使うのが常識。 ・RSSライブラリで同じものを書くと 多少省略しているが、本質的なところは同じ。 添付ライブラリだけ 80行 RSSライブラリ使用 30行足らず ○PHP PEARというクラスライブラリにそのままズバリのものがあるのでそれを使ってみた。 サンプルを切り貼りしたものなので解説するところはない。 '=&' というのが参照になる。 ・プロキシ対応 インスタンスを作るときに URL を指定するが、プロキシに対応していない。 プロキシするならストリームのラッパー作るなど工夫が必要になる。 ・動作 これで引っ張ってきてパースすると結果がハッシュに入るので、foreach でまわして表示しておしまい。 ・文字コード UTF8 -> EUC-jp に変換しているのは kterm で debug していたから。 UTF8から変換しない場合は、該当行は不要となる。 ・PHPのクラスライブラリ デフォルトでは入らない。 コマンドラインでインストールしたいクラスライブラリを指定するとネットワークインストールできる。 設定をちゃんとすると、プロキシ対応しているのでファイアウォールの内側でもインストールには問題ない。 5.質疑応答・議論の流れ、内容 Q. CPAN の Cの発音 について、もっと詳しく教えて欲しい。 A. クパンについては、会社では 自分以外は間違った発音をしている。 (司会: できればプログラムに対する質問をお願いします。) Q. RSSライブラリを使っている場合と、使っていない場合でそれぞれどれくらいの行数か。 A. (Ruby) 使わない場合 80行、使った場合 3、40行。 (Python) 素の SAX でしか作っていない。 (Perl) 試していないからわからないが、正規表現を駆使すればワンライナーで書けるかも。 (PHP) 行指向では倍だったので、もっと増えると思うので50行くらいか。 関数があれば楽だが、無ければかなり悲惨。 Q. テンプレートライブラリ使っていないものもあるが、サニタイズはどうなっているのか? クロスサイトスクリプティングをくらう可能性があるのではないか。 (Ruby) 簡単にするため、サニタイズしていない。 サニタイズするならCGIクラスにあるescapeHTMLメソッドが使える。 (Python) rssgetpy の 38行目で escapeモジュール の escape関数 を使っている。 '&' '>' '<' '"' を エンティティ参照へ変換するだけのもの。 他は特に加工しているところはない。 (PHP) サニタイズ関数が用意されているのでそれを呼んだり、全自動でやって欲しいというフラグを立てる。 DBについても、SQLインジェクションをするためにメタ文字やnull文字は自動的にエスケープしたり復元したりする機能が、言語の方で用意されている。 テンプレートの方はよくわからないがあると思う。 (Perl) Perl のテンプレートキットでも標準のフィルタという仕組みがある。 HTMLフィルタなどでそこらへんの処理をすることができる。 独自のフィルタも簡単に登録できる。 6.発表の総括 7.所感 8.特記事項 (特になし) $Id: p3-1.log,v 1.1 2004/03/24 04:00:36 ryuchi Exp $