連載 .NETでWindowsアプリを作ろう

第1回 Google画像検索アプリを作ろう

デジタルアドバンテージ 遠藤 孝信
2005/06/25
Page1 Page2 Page3

Web画像用のWebImageクラスの作成

 では、さっそくプログラミングしていきましょう。

■Web画像を表すデータ構造

 WebImageSearchでサムネイル画像を表示するために、Webでの画像検索の結果として必要となるデータは次の3つです。

  • サムネイル画像のURL
  • 元画像のURL
  • 画像を含むページのURL

 ここでは最初に、これら3つのデータを保持するクラスをWebImageクラスとして定義します。各プラグインはWebでの検索結果をセットしたWebImageクラスのオブジェクトを作成し、その配列をメイン・ウィンドウに返すことになります。実際のコードは次のようになります。

public class WebImage
{
  string smallImage;
  string largeImage;
  string page;

  public WebImage(string s, string l, string p)
  {
    smallImage = s;
    largeImage = l;
    page = p;
  }

  public string SmallImageURL { get { return smallImage; } }
  public string LargeImageURL { get { return largeImage;  } }
  public string DetailPageURL { get { return page; } }
}
Public Class WebImage
  Dim smallImage As String
  Dim largeImage As String
  Dim page As String

  Public Sub New(ByVal s As String, ByVal l As String, ByVal p As String)
    smallImage = s
    largeImage = l
    page = p
  End Sub

  Public ReadOnly Property SmallImageURL() As String
    Get
      Return smallImage
    End Get
  End Property

  Public ReadOnly Property LargeImageURL() As String
    Get
      Return largeImage
    End Get
  End Property

  Public ReadOnly Property DetailPageURL() As String
    Get
      Return page
    End Get
  End Property
End Class
Webから得られた画像を表すWebImageクラス(上:C#、下:VB.NET)

 いったん作成されたWebImageオブジェクトは、メイン・ウィンドウでそれぞれの値を読み出すだけなので、読み取り専用のプロパティのみを用意しておきます。

■プロジェクトの作成

 ではここでVisual Studio .NET(以降、VS.NET)を起動して、WebImageクラスを書き込んでいきましょう。

 ここではまず、アプリケーションのメイン・ウィンドウとなる「WebImageSearch」プロジェクトを作成します。これは新規プロジェクトとして「Windowsアプリケーション」を作成します。

Windowsアプリケーションのプロジェクトを新規作成したVS.NETの画面

 最終的には、このフォーム上にコントロールを配置してメイン画面を設計するのですが、それは第3回で行う予定です。今回はWebImageクラスを記述するために、いま作成したプロジェクトに別の新規プロジェクトとして「WebImageLib」を追加します。

 これには、次の画面のようにして新しいプロジェクトを追加します。

ソリューションへの新しいプロジェクトの追加
ソリューション・エクスプローラで[ソリューション]を選択し、右クリックして[追加]−[新しいプロジェクト]を実行する。

 新しいプロジェクトでは、テンプレートとして「クラス・ライブラリ」を選択します。そしてWebImageプロジェクトに含まれるファイル(ここでは「Class1.cs」を「WebImage.cs」にしました)に、先ほどのWebImageクラスを書き込みます。

 このようにしてプロジェクトを新たに追加した場合、ソリューションをビルドすると、最初に作成したプロジェクトで生成されるWebImageSearch.exeのほかに、追加したプロジェクトで生成されるWebImageLib.dllの2つが出来上がります。これらは次のようなパスで作成されているはずです(C#の場合。「D:\WebImageSearch\」の部分はプロジェクトを作成したディレクトリ)。

  • D:\WebImageSearch\WebImageSeaerch\bin\Debug\WebImageSearch.exe
  • D:\WebImageSearch\WebImageLib\bin\Debug\WebImageLib.dll

 このようにプロジェクトを分けたのは、アプリケーション本体とは別に作成するプラグインからもWebImageクラスの定義(WebImageLib.dll)を参照できるようにするためです。

Googleイメージ検索における検索の詳細

 続いてはGoogleのイメージ検索を行う部分(Google用プラグイン)を実装していきます。これは、検索結果のページ(HTMLデータ)をプログラムで受け取り、それを自分で解析して、(WebImageクラスのオブジェクトを組み立てるのに)必要なデータを取り出すという地道な作業となります。

 まず実際にブラウザでGoogleを検索してみましょう。ここでは「C#」というキーワードで検索してみます。

Googleのイメージ検索で「C#」を検索した結果

 検索結果ページのHTMLデータ(ソース)をよく見ると、画像を表示している部分はすべての次のような構造になっているのが分かります。

<td align=center valign=middle width=23%> <a href=/imgres?imgurl=http://www.xtreme-simplicity.net /metrics2.gif&imgrefurl=http://www.xtreme-simplicity.net/ &h=740&w=892&sz=37&tbnid=eoQ2JPmD294J:&tbnh=120&tbnw=145&hl=ja& start=1&prev=/images%3Fq%3Dc%2523%26svnum%3D100%26hl%3Dja%26lr%3D%26c2coff%3D1%26sa%3DG><img src=/images?q=tbn:eoQ2JPmD294J:www.xtreme-simplicity.net/ metrics2.gif width=145 height=120></a></td>
1つの画像を表示するためのHTMLデータ(Googleイメージ検索の場合)

 この中で、WebImageオブジェクトを作成するのに必要な部分は緑色で示した3つの部分です(順に「元画像のURL」「画像を含むページのURL」「Googleがキャッシュしているサムネイル画像」)。プログラムでは、Stringクラス(System名前空間)の文字列操作メソッドを駆使して、「href=/imgres?」や「src=/images?」といった文字列を目印にこれらのURLを切り出していきます。

 もちろん、このようなHTMLデータに依存したコーディングは、Googleがデータの構造を少し変えてしまえば台無しになるものですが、そのときはあきらめてコードを修正することにします。

 余談になりますが、もしWebページがあらかじめ定められた形式(例えばXMLデータ)でデータを返すようになったとすると、それは「Webサービス」であるということになります(ちなみにWebサービスでは、そのインターフェイス(呼び出し手順)をサービス公開後に変更することは最もやってはいけないことの1つなので、インターフェイスは基本的に恒久なはずです)。

■検索結果のページ移動

 次は検索結果のページの移動について調べていきましょう。

 通常たいていの検索サイトは検索結果をページに分割して返します。Googleイメージ検索では1ページ当たり20件です(かつ、どんなに検索結果が多くても検索結果ページは50ページまでのようです)。プログラムでは基本的にすべてのページの検索結果を取得するので、対象となる検索結果のページ番号を指定できるようにしておく必要があります。

 Googleイメージ検索では、検索結果が表示されたときのページのURLは次のようになっています。

http://images.google.co.jp/images?q=C%23&hl=ja

 これは、「http://images.google.co.jp/images」というページに対して、「q=C%23」と「hl=ja」の2つのパラメータを渡しています。ここで「C%23」は「C#」をURLエンコードしたものです。日本語や一部の記号をURL中で使用する場合にはこのような変換が必要となります(「.NET TIPS:文字列をURLエンコードするには?」を参照)。

 プログラムからは、検索キーワードをURLエンコードしてから、上記のようなURLでWebにアクセスすれば、まず1ページ目のHTMLデータは受け取ることができます。

 さて、検索結果1ページ目から2ページ目へ進むと、URLは次のようになります。

http://images.google.co.jp/images?q=C%23&svnum=100&hl=ja&lr=&c2coff=1&start=20&sa=N

 ここでは7つのパラメータが指定されていますが、注目すべきは「start=20」で、これは検索結果を20件目から表示せよ、ということのようです。ほかのパラメータは仕様が公開されているわけではないので、それぞれが何を意味するのかははっきりいってよく分かりません。

 いろいろと試行錯誤した結果、プログラムからは次のようなURLを発行すれば、任意のキーワードで、任意の位置の検索結果のページを開けるようです。

http://images.google.co.jp/images?hl=ja&q=<検索キーワード>&start=<結果の表示開始番号>&filter=0&safe=off

 蛇足ながら、最後のパラメータである「safe=off」は、日本版Googleではアナウンスされていない、ある機能を無効にするオプションです。このパラメータの有無で検索結果がどのように変化するのかは実際に試してみてください。

■検索結果がまだあるかどうかの判定

 Googleイメージ検索の場合、検索結果が何ページになるのかを1回目の検索時に(検索結果の1ページ目の内容だけから)取得するのは大変そうなので、プログラムでは検索結果を取得した後は、続く検索結果ページがあるかどうかだけをチェックするようにします。

 このときに目印となるのは検索結果ページの一番下にある「次へ」というリンク文字列です。取りあえずこれがHTMLデータに含まれていれば、次のページがあるという判断ができます。

■検索部分とメイン・ウィンドウのインターフェイス

 以上で、プログラムでやるべきことが見えてきたので、先にメイン・ウィンドウとプラグインとの間のインターフェイスを決めておきましょう。ここでは次のようなインターフェイスを定義します。

public interface IWebImage
{
  // 表示用の検索サイトの名前
  string Name { get; }

  // 現在のページ番号
  int CurrentPage { get; }

  WebImage[] GetImages(string query); // 1ページ分の画像を取得
  bool MoveNext(); // 次ページに移動
  void Reset(); // 初期化
}
Public Interface IWebImage
  ' 表示用の検索サイトの名前
  ReadOnly Property Name() As String

  ' 現在のページ番号
  ReadOnly Property CurrentPage() As Integer

  ' 1ページ分の画像を取得
  Function GetImages(ByVal query As String) As WebImage()
  Function MoveNext() As Boolean  ' 次ページに移動
  Sub Reset()  ' 初期化
End Interface
プラグイン用のインターフェイス定義(上:C#、下:VB.NET)

 ここで中心となるメソッドはGetImagesメソッドです。このメソッドはWebから取得した画像をWebImageオブジェクトの配列として返すためのものです。これらのプロパティやメソッドの役割の詳細については後述します。

 WebImageSearch用のプラグインは、少なくともこのIWebImageインターフェイスで定義されている合計5つのプロパティやメソッドを、メソッド名とパラメータの数や並びをそのままに実装する必要があります。

 そして、もしそのように実装されていれば、メイン・ウィンドウ側ではIWebImageインターフェイスのオブジェクトに対して、それらのプロパティやメソッドを呼び出すことができます。メイン・ウィンドウからの呼び出しについては、プラグインについて取り上げる第4回で解説します。

 さて、このインターフェイスの定義もメイン・ウィンドウおよびプラグインの両方から参照するので、WebImageクラスと同じファイルに記述してビルドしておきます。これにより、ビルドされるDLLファイル(WebImageLib.dll)には、WebImageクラスとIWebImageインターフェイスの2つの定義が含まれることになります。このモジュールはこれで完成です。


 INDEX
  .NETでWindowsアプリを作ろう
  第1回 Google画像検索アプリを作ろう
    1.Web画像検索ツール「WebImageSearch」
  2.Web画像用のWebImageクラスの作成
    3.Google用プラグインの作成
 
インデックス・ページヘ  「.NETでWindowsアプリを作ろう 」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間