使ってみよう! Bing API/SDK

第21回使ってみよう! Bing API─⁠─Silverlight編(1)

はじめに

今回はSilverlightでBing APIを使ってみましょう。Silverlightを使用すれば、Webアプリケーションだけでなくクライアント アプリケーションも作成可能です。Silverlightについては詳しく説明しませんが、実行までの手順を初めての方でも理解できるよう紹介しています。一緒にBing APIによる検索アプリケーションを作ってみましょう。

前回までのjQueryでBing APIを利用したときは、次のようなURLにアクセスしてJSON形式のデータを取得していました。

  • http://api.bing.net/json.aspx?
      AppId=AppId&
      Version=2.2&
      Market=ja-JP&
      Query=Windows&
      Sources=Web

jQueryの場合と同様の方法をSilverlightでも記述できますが、Bing APIにはHTTPとXMLをベースとしたSOAPというプロトコルのサービスも提供されています。Silverlightから利用する場合は、SOAPのほうが便利です。今回はこのSOAPのBing APIを利用します。

開発環境

はじめに開発環境についてです。Silverlightでの開発は次の環境が必要です。あらかじめインストールを行ってください。

無償のVisual Web Developer Express 2010 ExpressとSilverlight 4 Toolsの組み合わせでも開発できます。Visual Web DeveloperはMicrosoft Web Platform Installer内に含まれています。

またデザイナツールのExpression Blend 4もあるとよいですが、今回は使用しません。

ライブラリーのインストール

Silverlightアプリケーション開発には必須ではありませんが、今回のアプリケーションでは、Reactive Extensions for .NETというライブラリーを使用して非同期処理を行っています。DevLabsから「Rx for Silverlight 4」をダウンロードしインストールを行ってください(Webページの右側の「Get Rx」にダウンロードのボタンがあります⁠⁠。

Bing APIサービスの参照

それでは、Bing APIをSilverlightで利用してみましょう。まず、Visual Studioでプロジェクトを作成して、サービスの参照という手順を踏んで、Bing APIを利用するクラスを自動生成するところまで説明します。

プロジェクトの作成

まず、Visual StudioでSilverlightアプリケーション プロジェクトを作成します図1⁠。ここではプロジェクト名を「BingApiSample」にしています。また、この連載ではVisual Basicを使用します。

図1 Silverlightアプリケーション プロジェクトの新規作成
図1 Silverlightアプリケーション プロジェクトの新規作成

OKボタンをクリックすると、図2のようにSilverlightアプリケーションを新しいWebサイトでホストするか聞かれますので、図のようにそのままOKボタンをクリックします。

図2 Silverlightアプリケーションを新しいWebサイトでホスト
図2 Silverlightアプリケーションを新しいWebサイトでホスト

以上で新しい Silverlight アプリケーション プロジェクトと、そのアプリケーションを表示するためのWebアプリケーション プロジェクトが作成されました。この後、特に指定がなければ扱うプロジェクトはSilverlightアプリケーション プロジェクトのほうです。

最初にインストールしたライブラリーも使用できるようプロジェクトに参照を追加しておきましょう。Visual Studioプロジェクト メニューの参照の追加から、次の3個のコンポーネントを追加します図3⁠。

  • System.CoreEx
  • System.Observable
  • System.Reactive
図3 参照の追加
図3 参照の追加

サービス参照の追加

SOAPによるWebサービスの利用は、特定のURLへリクエストをXML形式のデータで送信し、レスポンス データをXML形式で受信することで行います。HTTPで送受信するコードを直接記述してもよいですが、SOAPではWebサービスにどのようなメソッドやどのようなデータを送受信すればよいかが定義されています。そのため、Visual Studioを利用すると、Webサービスにアクセスするクラスの自動生成が可能です。

プロジェクト メニューからサービス参照の追加を選択します。開いたウィンドウにあるアドレス欄に以下のURLを入力します。

  • http://api.bing.net/search.wsdl?AppID=AppID&Version=2.2

このアドレスがBing APIのサービスを定義しているURLです。AppIDパラメーターにはApplication ID(AppID)を指定してください。AppIDの取得は第19回で紹介しています。

移動ボタンをクリックするとBing APIで提供されているサービス内容が確認できます図4⁠。Searchというメソッドのみ定義されていることがわかります。名前空間に適当な名前を入力しOKボタンをクリックして、サービス参照を追加します。ここでは名前空間を「ServiceReference」にしています。

図4 サービス参照の追加
図4 サービス参照の追加

以上で、Bing APIにアクセスするBingPortTypeClientというクラスが作成されています。

Webサイトの検索

次にBing APIを利用してWebサイトを検索します。検索クエリーを入力と、結果の表示をするために画面を作成してから、コードを記述します。

画面の作成

SilverlightではXAMLと呼ばれるXMLベースの言語によって画面が構成されています。今回は直接XAMLを記述して画面を作成します。ソリューションエクスプローラーからMainPage.xamlを選択しデザイナーを表示します図5⁠。

図5 デザイナーの表示
図5 デザイナーの表示

※図では、この後に示すコードを入力済みです。

ここに、テキストボックス(TextBox⁠⁠、ボタン(Button⁠⁠、リストボックス(ListBox)を追加します。それぞれ検索クエリーの入力、検索の実行、結果の表示に使用します。XAMLのコードは次のようになります。はじめから記述されている要素部分を下記のコードと置き換えます。

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <TextBox x:Name="QueryTextBox" Margin="5" />
        <Button x:Name="SearchButton" Grid.Column="1" Margin="5" Width="80"
                Content="検索" />
    </Grid>
    <ListBox x:Name="ResultListBox" Grid.Row="1" Margin="5" />
</Grid>

この後にも編集しますが、ひとまず画面の作成は以上です。まだ何も動作しませんが、デバッグ メニューからデバッグの開始をすると、図6のようにWebアプリケーションが実行されます。

図6 実行結果 画面の確認
図6 実行結果 画面の確認

コードの記述

続いてAPIの呼び出しなどを行うコードを記述します。ソリューションエクスプローラーからMainPage.xaml.vbを開きます。名前空間の記述を省略できるよう、以下のコードを先頭にまず記述しておきましょう。

Imports BingApiSample.ServiceReference

次に、検索処理と結果の表示を行うSearchメソッドを作成します。MainPageクラス内に次のコードを追記してください。

Private Sub Search(ByVal query As String)
    If query = "" Then
        ' クエリーが指定されていない場合は処理を抜ける
        Exit Sub
    End If

    ' (ここに Bing API の呼び出し処理を記述)
End Sub

ボタンをクリックしたとき、Searchメソッドを実行します。次のようにコンストラクタでClickイベントの関連付けを行っておきます。

  Public Sub New()
      InitializeComponent()
      AddHandler SearchButton.Click, Sub() Search(QueryTextBox.Text)
  End Sub

検索処理の手順は次のように行います。必ずしもこうしなければならないというものではありません。

  1. BintPortTypeClientオブジェクトの生成
  2. 検索が完了したときの処理を定義(リストボックスにレスポンス内容を表示)
  3. 検索リクエストの作成
  4. 検索API呼出し

まずBintPortTypeClientオブジェクトを生成します。自動生成されたクラスでしたね。

Dim client = New BingPortTypeClient

APIの呼出しは非同期で行います。レスポンスを受信(検索結果を取得)したとき、BingPortTypeClientオブジェクトのSearchCompletedイベントが発生します。その時の処理を以下のように記述します。ここでは単にListBoxのItemsSourceプロパティに検索結果のオブジェクトをそのまま指定しています。

' API 呼出し完了したときの処理(リストボックスに結果を表示)
Observable.FromEvent(Of SearchCompletedEventArgs)(client, "SearchCompleted") _
    .Take(1) _
    .Subscribe(
        Sub(e)
            If e.EventArgs.Error Is Nothing Then
                Dim result = e.EventArgs.Result
                ResultListBox.ItemsSource = If(result.Web IsNot Nothing, result.Web.Results, Nothing)
            End If
        End Sub)

リクエストの作成は次のようになります。AppIDや検索クエリーなど検索の全般的な設定を指定は、SearchRequestオブジェクトを使用し、Webサイトの検索に関するリクエストは、WebRequstオブジェクトを使用します。Webサイト検索の場合、SearchRequestオブジェクトのSourcesプロパティにSourceType.Webを指定し、WebプロパティにWebRequestオブジェクトを指定します。

' SearchRequest と WebRequest の作成
Dim request = New SearchRequest With {
    .AppId = "AppID",
    .Market = "ja-JP",
    .Query = query,
    .Sources = {SourceType.Web},
    .Web = New WebRequest With {
        .Offset = 0,
        .Count = 10}
}

最後に、検索を実行します。

client.SearchAsync(request)

ここまでを実行してみましょう。テキストボックスにクエリーを入力し検索ボタンをクリックすると図7のようになるかと思います。

図7 実行結果 検索結果の表示
図7 実行結果 検索結果の表示

リストボックスにWebサイトの検索結果WebResultオブジェクト)のコレクション(コードではe.EventArgs.Result.Web.Results)を追加しただけですので、WebRe sultオブジェクトが持つWebサイトのタイトルや説明は正しく表示されません。次は正しく結果が表示されるようデザイナーでXAMLをもう一度編集しましょう。

デザインの編集

リストボックスに表示される項目(ListBoxItem)のデザインを編集します。<ListBox>要素の部分を次のように変更してください。

<ListBox x:Name="ResultListBox" Grid.Row="1" Margin="5"
         ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Margin="0 0 0 10">
                <HyperlinkButton NavigateUri="{Binding Url}" TargetName="_blank">
                    <TextBlock Text="{Binding Title}" />
                </HyperlinkButton>
                <TextBlock Text="{Binding Description}" TextWrapping="Wrap" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

検索結果のデータの表示方法は、Silverlightのデータバインディングと呼ばれる方法を用いています。上記コードでは「Text={Binding Title}」のように記述することで、TextBlockのTextプロパティにListBoxのItemsSourceプロパティに指定したコレクションの各アイテム(WebResultオブジェクト)のTitleプロパティの値を指定しています。

もう一度、実行して確認すると図8のようになります。

図8 実行結果 リストボックスの項目の編集
図8 実行結果 リストボックスの項目の編集

以上で、Webサイトの検索ができるようになりました。XAMLを編集することで自由に見た目を変更できます。

Webサイト検索結果のプロパティ

使用したWebResultオブジェクトのプロパティは、Title・Url・Descriptionプロパティのみでしたが、WebResultオブジェクトには次のプロパティが用意されていますので、活用してみてください。

名前 説明
DateTime 最終更新日またはクロールした時間
例: 2011-03-30T07:20:00Z
Description 説明(検索語が含まれるWebページの文章の一部)
DeepLinks Webサイトに含まれるリンク(DeepLinkオブジェクト)のコレクション
各アイテムはTitleとUrlプロパティを持っています。
DisplayUrl 表示用のURL
SearchTags 検索用タグ(SearchTagオブジェクト)のコレクション

<meta>タグのname属性が「search.」ではじまるとき、nameとcontent属性の値が、NameとValueプロパティで参照できます。

Title Webサイトのタイトル
Url WebサイトのURL
CacheUrl WebサイトのキャッシュのURL

ただし、これらのプロパティはかならず含まれているわけではありません。次のようにXAMLを編集すると、すべての値を確認できます。

<ListBox x:Name="ResultListBox" Grid.Row="1" Margin="5"
         ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Margin="0 0 0 10">
                <HyperlinkButton NavigateUri="{Binding Url}" TargetName="_blank">
                    <TextBlock Text="{Binding Title}" />
                </HyperlinkButton>
                <TextBlock Text="{Binding Description}" TextWrapping="Wrap" />
                <TextBlock Text="{Binding DateTime}" />
                <TextBlock Text="{Binding DisplayUrl}" />
                <TextBlock Text="{Binding CacheUrl}" />
                <ListBox Margin="10 0 0 0" ItemsSource="{Binding DeepLinks}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <HyperlinkButton NavigateUri="{Binding Url}" TargetName="_blank" Content="{Binding Title}" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
                <ListBox Margin="10 0 0 0" ItemsSource="{Binding SearchTags}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding Name}" />
                                <TextBlock Text="{Binding Value}" Margin="5 0 0 0" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

送受信内容の確認

ここで、必須の内容ではありませんが、Bing APIの呼出し時のBing APIサーバーとの通信内容を見てみたいと思います。HTTPの通信内容を見るのにFiddler2というツールを使用します。

確認方法は簡単です。Fiddler2を起動後、作成したSilverlightアプリケーションで検索を実行します。すると、キャプチャリングした通信内容が表示されます図9⁠。

図9 Fiddler2でBing API呼出しをキャプチャリング
図9 Fiddler2でBing API呼出しをキャプチャリング

Visual Studioを使用したため実際の通信処理の部分は隠ぺいされた形になっていましたが、実際に通信内容を確認すると、http://api.bing.net/soap.asmxにアクセスし、リクエスト・レスポンスデータがXML形式でやりとりされていることがわかります。

画像の検索

作成したSilverlightアプリケーションのコードを変更して、画像の検索をしてみましょう。

まず、MainPage.xaml.vbのSearchメソッド内の変更です。API 呼出し完了したとき、Web.Resultsコレクションではなく、Image.ResultsコレクションをListBoxのItemsSourceに指定します。

' API 呼出し完了したときの処理(リストボックスに結果を表示)
Observable.FromEvent(Of SearchCompletedEventArgs)(client, "SearchCompleted") _
    .Take(1) _
    .Subscribe(
        Sub(e)
            If e.EventArgs.Error Is Nothing Then
                Dim result = e.EventArgs.Result
                ResultListBox.ItemsSource = If(result.Image IsNot Nothing, result.Image.Results, Nothing)
            End If
End Sub)

リクエストの作成も次のようにImageRequestオブジェクトとSourceType.Imageを指定するようにします。

' SearchRequest と ImageRequest の作成
Dim request = New SearchRequest With {
    .AppId = "AppID",
    .Market = "ja-JP",
    .Query = query,
    .Sources = {SourceType.Image},
    .Image = New ImageRequest With {
        .Offset = 0,
        .Count = 10}
}

次は、MainPage.xamlの変更です。<ListBox>要素を次のように変更します。

<ListBox x:Name="ResultListBox" Grid.Row="1" Margin="5"
         ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Margin="0 0 0 10">
                <HyperlinkButton NavigateUri="{Binding Url}" TargetName="_blank">
                    <TextBlock Text="{Binding Title}" />
                </HyperlinkButton>
                <Image Source="{Binding Thumbnail.Url}" Width="{Binding Thumbnail.Width}" Height="{Binding Thumbnail.Height}" HorizontalAlignment="Left" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

画像の検索結果特有のThumbnailオブジェクトを<Image>要素で表示するように変更しました。実行結果は図10のようになります。

図10 実行結果 画像の検索
図10 実行結果 画像の検索

複数の対象を検索

Bing APIでは、Webサイトと画像などを1回のリクエストで同時に検索できます。ここでは、Webサイト、関連キーワード、画像を一度に検索して表示してみましょう。

同時に検索するには、SearchRequest オブジェクトのSourcesプロパティに複数の種類を指定するだけです。MainPage.xaml.vbのリクエスト作成部分は次のようになります。

' SearchRequest の作成
Dim request = New SearchRequest With {
    .AppId = "AppID",
    .Market = "ja-JP",
    .Query = query,
    .Sources = {SourceType.Web, SourceType.RelatedSearch, SourceType.Image},
    .Web = New WebRequest With {
        .Offset = 0,
        .Count = 10},
    .Image = New ImageRequest With {
        .Offset = 0,
        .Count = 10}
}

関連キーワードのオプションはないため、WebRequestやImageRequestに相当するものはありません。

次に、XAMLを編集して結果を同時に表示できるようにしましょう。<ListBox>要素部分を次のコードに置き換えます。ListBoxを3個、横に並べています。

<Grid Grid.Row="1">
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

    <!-- 関連キーワード -->
    <ListBox x:Name="KeywordResultListBox" Margin="5" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <HyperlinkButton NavigateUri="{Binding Url}" Content="{Binding Title}" TargetName="_blank" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <!-- Webサイト -->
    <ListBox x:Name="WebResultListBox" Grid.Column="1" Margin="5" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="0 0 0 10">
                    <HyperlinkButton NavigateUri="{Binding Url}" Content="{Binding Title}" TargetName="_blank" />
                    <TextBlock Text="{Binding Description}" TextWrapping="Wrap" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <!-- 画像 -->
    <ListBox x:Name="ImageResultListBox" Grid.Column="2" Margin="5" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Margin="0 0 0 10">
                    <HyperlinkButton NavigateUri="{Binding Url}" Content="{Binding Title}" TargetName="_blank" />
                    <Image Source="{Binding Thumbnail.Url}" Width="{Binding Thumbnail.Width}" Height="{Binding Thumbnail.Height}" HorizontalAlignment="Left" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

MainPage.xaml.vbに戻って、API 呼出し完了時の処理を変更します。3種類の検索結果をそれぞれのListBoxのItemsSourceプロパティにしているだけです。

' API 呼出し完了したときの処理(リストボックスに結果を表示)
Observable.FromEvent(Of SearchCompletedEventArgs)(client, "SearchCompleted") _
    .Take(1) _
    .Subscribe(
        Sub(e)
            If e.EventArgs.Error Is Nothing Then
                Dim result = e.EventArgs.Result
                KeywordResultListBox.ItemsSource = If(result.RelatedSearch IsNot Nothing, result.RelatedSearch.Results, Nothing)
                WebResultListBox.ItemsSource = If(result.Web IsNot Nothing, result.Web.Results, Nothing)
                ImageResultListBox.ItemsSource = If(result.Image IsNot Nothing, result.Image.Results, Nothing)
            End If
        End Sub)

実行結果は図11のようになります。

図11 実行結果 複数の対象を検索
図11 実行結果 複数の対象を検索

おわりに

今回のアプリケーションを公開する場合は、Webアプリケーションプロジェクトにある次の3個のファイルをWebサーバー(Windows Serverである必要はありません)上に配置するだけです。

  • ClientBn/BingApiSample.xap
  • BingApiSampleTestPage.html
  • Silverlight.js

Webサーバーによっては、xapファイルが公開できるようMIME Typeをapplication/x-silverlight-appに設定する必要があります。

また、Silverlightアプリケーション プロジェクトのプロパティで、Silverlightタブにある「アプリケーションのブラウザー外実行を有効にする(B)」を有効にすると図12⁠、クライアントPCにアプリケーションのインストールができるようになります図13⁠。

図12 ブラウザー外実行の有効
図12 ブラウザー外実行の有効
図13 Silverlightアプリケーションのインストール
図13 Silverlightアプリケーションのインストール

これが冒頭で紹介した、Silverlightのクライアント アプリケーションです。

今回は以上です。いかがでしたでしょうか。次回もSilverlightによるBing APIの利用を紹介する予定です。

おすすめ記事

記事・ニュース一覧