解説: ウェブ上のサービスを利用して...

ウェブには情報検索を始め、辞書や機械翻訳、電車の乗り継ぎ検索、地図情報 などじつに様々な情報資源があります。また、なにか商品を購入しようかと考えて いる場合には、価格の比較や、その商品の評判もすぐに調べることができます。

ここでは車の評判検索を例に取り、このような他のサイトのサービス(情報資源)を「利用」して 自分なりのページを作り上げることを考えましょう。 (これは道義的な問題が生じる可能性がありますが、あくまでも個人使用なら問題はありません)

今回の学習項目です。

課題1. Yahoo情報検索サービスを利用する

課題1-1. Yahoo情報検索サービスの仕組み

最初にYahooの検索ページを例に取りましょう。 ここで、「Ruby」を検索してみるとどうなるでしょうか。 ちゃんと Ruby に関するページの情報が得られることでしょう。

ここでは、注目すべきはその内容ではなく、ブラウザの上に表示される 「ナビゲーションバー」の情報です(もしも、それが表示されないような設定 になっている場合には、ブラウザーの「表示」のオプションを変更して、 表示できるようにしてください)。きっと次のような表示が出たことでしょう。

 http://search.yahoo.co.jp/search?tt=c&ei=UTF-8&fr=sfp_as&aq=-1&oq=&p=ruby&meta=vc%3D

本講義によってCGIの仕組みを学んできた皆さんには、それぞれのパラメタの 意味は分からないとしても、どのような名前のCGIプログラムがどのような パラメタと値によって動いたかはお分かりかと思います。

実はYahooでは、それぞれのパラメタの意味や取りうる値について、 ちゃんと説明してくれています。 Yahooの検索ヘルプページから、 「サイト管理者向けヘルプ」 に行き、そこの「関連リンク」にある 「Yahoo!検索(ウェブ検索)の検索パラメータ仕様について(URLの意味)」、そのページの中の 「Yahoo!検索(ウェブ検索)」へとたどってください。

今までの学習とYahooの解説に基づき、Yahooの情報検索を行ったときにナビゲーションバーで表示されるURI

 http://search.yahoo.co.jp/search?tt=c&ei=UTF-8&fr=sfp_as&aq=-1&oq=&p=ruby&meta=vc%3D
の意味を説明してください。 また(1)結果の1ページあたりの表示を40件、(2)ファイル形式をpdf、(3)最終更新日を過去3か月 として検索をかけるとすれば、どのようなURIの表示になるかを答えてください。

課題1-2. Yahoo情報検索サービスの結果の取り込み

ブラウザではなくRubyのプログラムによって、Yahooの検索結果をファイルに出力することを考えましょう。 こうして得られたファイルは後で見るように、ブラウザを用いて得られる結果のページの「ソース」と同じものです。以下のプログラムを作成し、 このプログラムが出力したファイルYahoo.htmlと、「Ruby」を検索キーワードとしてYahoo検索して得られたページ(のソース)とを比較しなさい。

 require 'open-uri'
 fin=open("http://search.yahoo.co.jp/search?tt=c&ei=UTF-8&fr=sfp_as&aq=-1&oq=&p=ruby&meta=vc%3D")
 fout = open("Yahoo.html","w")
 while (line=fin.gets)
    fout.print line
 end
 fin.close
 fout.close
[open-uriとは]

open-uriとは、指定されたURI(少し前まではURLと言っていました。ウェブ上のファイルなどリソースへのパス(経路)情報の表記のことです。例えばhttp://www.st.chukyo-u.ac.jp/index.htmlがそれです)を普通のファイルと同様にアクセスするためのライブラリです。この例では、

fin=open("http://search.yahoo.co.jp/search?tt=c&ei=UTF-8&fr=sfp_as&aq=-1&oq=&p=ruby&meta=vc%3D")
 while (line=fin.gets)
    fout.print line
 end
によって、Yahooの検索ページ(これ自体はCGI)を開き、そこからgetsメソッドで内容を読み込んでいます。

[ページのソースの表示]

ブラウザでウェブのページを表示させたとき、元のウェブサイトから送られて来るデータは (一般に)HTML文書であることはお分かりかと思います。ウェブはそのタグに書かれた指令 によって文書を整形して表示しています(この他に、JavaScriptのようなスクリプト言語 によって書かれたプログラムを実行することで動的にページを変化させるなど、 ということも行われています)。

ブラウザで整形表示された元のページ、つまり「ソース」を見る方法は、ブラウ ザによって異なります。FireFoxの場合は、マウスの右ボタンをクリックして 表示されたポップアップメニュから「ページのソースを表示」を選びます。 IEの場合は「表示」メニューから「ソース」を選びます。

ただし、ブラウザによってはソースの文字コードを正しく判別できない場合が あります。その時には「文字化け」が起こります。これを戻すには、ページの 内容を一旦「名前を付けて保存」し、TeraPadで開けばよいでしょう。

課題1-3. Yahoo情報検索の結果ページの分析と編集

課題1-2で得られたYahoo.htmlの中身をTera Padで見てみましょう(これはUnicodeで書かれていますので、他のエディタだと文字化けして読めないことがあります)。 これをブラウザで表示した結果を比較すると、<div id="web">の後にある <li>がそれぞれページのタイトルとリンク先の情報の印になっていることがわかるでしょう。 このことを利用して、Yahoo.htmlから以下のような出力を行うプログラムを書きなさい。

 1. オブジェクト指向スクリプト言語 Ruby --- http://www.ruby-lang.org/ja/
 2. Ruby Programming Language --- http://ruby-lang.org/
 3. Ruby - Wikipedia --- http://ja.wikipedia.org/wiki/Ruby
 4. Ruby入門 --- http://www.rubylife.jp/ini/
 (以下略) 

ただしこの課題を推敲するには「正規表現」の知識が必要でしょう。この課題 を取り組む前に、 正規表現の学習を行ってください。

課題2: 車のレビューサイトを利用する

ここでの課題は、車のレビューサイトにアクセスして、そこに書かれたレビューの「まとめ」ページを作る、というCGIを作ることを目的とします。ここではみんカラというサイトを対象とします。このサイトでは車種がメーカー、ジャンル、カテゴリで分類されています。たとえばメーカーとしてトヨタを指定すると、トヨタの車を写真付きで選ぶようになっています。

ためしにプリウスを選んでみましょう。するとプリウスの情報ページが表示されます。そこではプリウスの情報だけではなく、愛車紹介、燃費記録などと並んで、「オーナーによるレビュー」へのリンクがあります。

課題2-1. 数秒後に別なページを呼び出すための書き方

今までサービスしていたページのサイトを変更することが時々あります。その場合に困るのは、サイトの変更のお知らせの方法です。相変わらず古いサイトのページにアクセスされることがあるからです。

そこで次のようなHTML文書を元のページの内容としておけば、新しいサイトに移ったことを知らせるだけではなく、訪れた人に手間をかけさせずに新しいページに誘導することができます。

<HTML>
<HEAD>
<meta http-equiv="refresh" content="5;http://cgi.st.chukyo-u.ac.jp/z189105/newHome.html">
<title>ページ移転のお知らせ</title>
</HEAD>
<BODY>
<h1>このページは新しいサイト http://cgi.st.chukyo-u.ac.jp/z189105/newHome.html に移転しました。
5秒後に自動的に移動します。</h1>
</BODY>
</HTML>

HEAD部に書かれたmetaタグのパラメタ「http-equiv="refresh" content="5;http:..."」 がその鍵です。「5」は「5秒後」に移動することを指定してます。5以外の適当な整数が 指定できます。この後の「;」に続くURIが移動先を示しています。

この機能を使って、みんカラのレビューページを表示するCGIをつくることを考えましょう。

みんカラのレビューページのURIは規則性があります。例えばプリウスのレビューのURIがhttp://minkara.carview.co.jp/car/toyota/prius/review/であったことからわかるように、http://minkara.carview.co.jp/car/に続けて、メーカー名、車種名、reviewとなっています。 メーカー名はトヨタの場合はtoyota、日産の場合はnissan、ホンダの場合はhondaです。また車種名は、プリウスならprius、スカイラインならskyline、フィットならfitとなっています。 このことを前提として、パラメータmakerの値としてtoyotaかnissanかhondaを受け取り、またパラメータcarの値としてprius、skyline、fitを受け取り、そこからレビューページへのURIを作って、そのページを表示する(つまり、自動的に「そのレビューページに移動する」ページを出力する)CGIプログラムを作成しなさい。

[ヒント]

久しぶりにCGIを作るので、やり方を忘れてしまったかもしれませんね。 CGIプログラムは、パラメターの値を受け取り、それに基づいてHTML文書をprintするプログラムです。 したがって、この課題のためのCGIの書き出しは以下のようになるでしょう。なお、出来上がったら、CGIファイルのパーミッションの設定などのチェックをすることをお忘れなく。

#! /usr/local/bin/ruby
$KCODE = "e"
require 'cgi'
param = CGI.new
maker = param['maker']
car = param['car']

print <<EOS
Content-type: text/html; charset=euc-jp

<HTML>
...
...   ここにHTMLの文書の中身を書く。適切なmetaタグを書くのをお忘れなく
...
</HTML>
EOS

課題2-2. みんカラのレビューページの取出し

次にあげる例にならって、メーカー名としてトヨタ、日産、ホンダを選び、車種はそれぞれのメーカーから代表的な車を10車種程度の中から選べるページを作りなさい。そして「実行」ボタンが押されれば、そのレビューページが表示される課題2-1のCGIプログラムを呼び出して、レビューページを表示するようにしなさい。

参考: レビューページを選択表示するためのページの例

課題2-3. レビューページを見比べるページの作成

課題2-2ではひとつのページしか表示できませんでした。二つ(以上の)ページを並べて表示できれば、特徴が似た車種を見比べることが可能になります。 そこで使われるのがフレームという機能です。フレームはHTML文書のBODY部に書かれ、ウィンドゥを幾つかに区切ってそれぞれに別な文書を表示させることができるようになります。例えば、ウィンドゥを左右1つずつ同じ幅のフレームで分割表示させたい場合は

<FRAMESET COLS="50%,50%">
  <FRAME SRC="frame1.html" />
  <FRAME SRC="frame2.html" />
</FRAMESET>
と書けば、左に frame1.html が、右に frame2.htmlが、それぞれ同じ幅のフレームとして表示されます。ここで「50%」と書いたのは全体の幅を100%としてそれぞれどのくらいの幅を占めるかを指定したのです。この値を適当に設定すれば、左右違う幅のフレームができあがります。なお、%を書かなければ50という数は「ピクセル数」と解釈されます。そこで、次のように書くと
<FRAMESET COLS="200,*">
  <FRAME SRC="frame1.html" />
  <FRAME SRC="frame2.html" />
</FRAMESET>
左のフレームは200ピクセル、右は残り全部の幅が割り当てられます。

このようにフレームを用いるのは便利なのですが、分割したフレームに表示できるのは基本的に自分のサイトのページに限られます。つまり他のサイトにあるページへのURIは指定できません。

そこで、課題2-1のCGIを利用することとしましょう。課題2-2で作成したページを修正し、これから作成するCGIプログラムを呼び出すようにします。このCGIプログラムは、フレームを利用してウィンドゥを分割表示するHTML文書を出力します。それぞれのフレームのSRCには、それぞれ指定されたメーカーと車種の値を課題2-1のCGIに渡すURIを書きます。そのようなCGIプログラムはおおよそ次のような構造をもつでしょう(ここでは簡単のため、トヨタと日産の車種のみが指定できるのとします。また課題2-1で作成したCGIファイルを ShowTheReview.cgi としています)。

#! /usr/local/bin/ruby
$KCODE = "e"
require 'cgi'
param = CGI.new
toyota= param['toyota']
nissan = param['nissan']

print <<EOS
Content-type: text/html; charset=euc-jp

<HTML>
<HEAD>
  <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
  <title>レビューの比較ページ</title>
</HEAD>
<BODY>
<FRAMESET COLS="50%,50%">
  <FRAME SRC="ShowTheReview.cgi?maker=toyota&car=#{toyota}" />
  <FRAME SRC="ShowTheReview.cgi?maker=nissana&car=#{nisasn}" />
</FRAMESET>
</BODY>
</HTML>
EOS

参考: レビューページの比較

課題2-4. 【発展】レビューページを見比べるページの作成

注意: この課題の達成には結構な作業量が必要です。 時間があればこの課題にチャレンジしてください。

課題2-3では、みんカラのページを「そのまま」使っていました。このページは大きな画面で読むように設計されていますので、比較ページで見るには見やすいものではありません。また、広告などもありすっきりしていません。

そこで、元のページを比較ページ用に「編集」して、その結果を表示することを考えます。 これには、正規表現の技術が必要で、ちょっとした作業が必要になります。

レビューページの比較改良版 がそのようなページの一例です(これは3つのメーカーから車を選べますが、比較ページに現れるのは2車種までです)。これを参考にして、見やすい比較ページを作ってください。

[レビューページの比較改良版の解説]

みんカラのレビューページへのアクセス数を少なくするため、ある車種のレビューの編集ページを作った時には、ファイルとしてセーブし、次回以降はそれを再利用するようにしています。そのやり方は、ファイル名を carPage とすれば、「ファイルcarPageをopenする前に」File.readable?(carPage)によってcarPageファイルがあるかどうかを検査することで実現しています。

もしもそのようなファイルがない場合は、みんカラのレビューページをopen-uriを用いて読み込みます。大きくレビューページは(1)車の画像や価格などの情報、(2)ユーザーからの評価をまとめた表、(3)個々のユーザーからのレビュー、という三つの部分に分かれていますので、 まずページの内容をキーワードを手がかりにしてこの三つに分け、それぞれの部分から該当する情報を取り出し、クラスのオブジェクトとして記録します。 特に(3)の部分は「ユーザーからのレビュー」がいくつかありますから、「一人一人のユーザーのレビュー」を ReviewArticle というクラスのオブジェクトとして扱うようにしています。以下はその定義です。

class ReviewArticle   # ユーザーレビューのクラス
  def initialize(d,c,p,l) 
     @date = d           # 日付
     @comment = c        # レビュー内容
     @evaluation = p     # 評価
     @link = l           # 元の記事へのリンク
  end # def
  attr_accessor :date,:comment,:evaluation, :link
  def showAsTable   # HTMLの表としての出力
     str =<<EOS
        <TABLE BORDER="2"> 
  	  <TR><TD width="100">#{@date} </TD><TD><A HREF="http://minkara.carview.co.jp#{@link}">もっと読む</A></TD></TR>
	  <TR><TD align="center">評価:  #{evaluation}</TD><TD width="800">#{@comment}</TD></TR>
	</TABLE>
EOS
     return str
  end # def
  def showAsText   # 単純に印刷した場合の表示   
     str =<<EOS
  	Date: #{@date}                        Evaluation: #{@evaluation}
  	Description: #{@comment} 
  	Link: http://minkara.carview.co.jp#{@link}
EOS
     return str
  end # def
end # Class of ReviewArticle

プログラミングIIIのホームに戻る