目次


Google ブック検索を PHP アプリケーションに統合する

PHP を使って Google ブック検索のデータを処理し、カスタム Web アプリケーションに統合する

Comments

はじめに

出版業界に何からの形で関わっている人や単なる熱心な読書家の耳にも、Google ブックスの噂は入ってくるに違いありません。Google ブックスは、何百万冊もの書籍をスキャンしてオンラインでプレビューまたは購入できるようにして、世界最大の検索可能なデジタル・ライブラリーを作成しようという Google の試みです。またこれは、Google のプロジェクトのなかでもとりわけ議論を呼んでいるものの 1 つでもあり、Google ブック検索に対する集団訴訟はごく最近の 2009年 11 月に和解したばかりです。

Google ブックスはうわさ話の恰好の種となっているだけではありません。その Data API によって、開発者にとっても興味深いプロジェクトとなっています。開発者はこの API を使用することで、Google ブックスのデータベースを読み取り、ユーザーが指定した基準と一致する書籍を検索して、その検索結果を他の Web アプリケーションで使用することができます。REST モデルに準拠したこの API には、XML 対応の開発ツールキットを使ってアクセスすることができます。この API にはすでに、PHP と Java™ の他、よく使われているプログラミング言語に対応したクライアント・ライブラリーがあります。

この記事では Google Book Search Data API を取り上げ、書籍の検索結果をカスタム PHP アプリケーションに統合して使用する手順を説明します。さらに、書籍をキーワード、言語、または著者を基準に検索する方法、書籍に関するデータ (ISBN 番号とサムネール画像を含む) を取得する方法、そしてデータベースに保管されている書籍にレビューおよび評価を追加する方法について、サンプル・コードを紹介しながら説明します。それでは早速、本題に入りましょう。

ブック検索のフィードについて

PHP コードに取り掛かる前に、Google Book Search Data API について少し説明しておきます。REST をベースとしたサービスの例に漏れず、この API は XML にエンコードされた 1 つ以上の入力がパラメーターとして含まれる HTTP リクエストを受け入れ、XML 対応のあらゆるクライアントで構文解析できるように XML にエンコードしたレスポンスを返します。Google Book Search Data API の場合、レスポンスは常に、要求された情報を含む Atom フィードとなります。

標準的なブック検索のフィードには、有用かつ関連するアプリケーションを構築するのに十分な情報が含まれています。実際のフィードを見るには、任意の Web ブラウザーで URL http://books.google.com/books/feeds/volumes?q=php にアクセスしてみてください。この REST メソッドは、キーワード php と一致する書籍のリストを返します。このメソッドに対する XML レスポンス (検索結果ページのソース・コードで確認することができます) には、リストアップされた書籍の詳細情報が含まれます。その一例をリスト 1 に示します。

リスト 1. Google ブック検索のフィード例
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' 
 xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
 xmlns:gbs='http://schemas.google.com/books/2008' 
 xmlns:dc='http://purl.org/dc/terms' 
 xmlns:gd='http://schemas.google.com/g/2005'>
  <id>http://www.google.com/books/feeds/volumes</id>
  <updated>2009-12-28T06:14:28.000Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind' 
   term='http://schemas.google.com/books/2008#volume'/>
  <title type='text'>Search results for php</title>
  <link rel='alternate' type='text/html' href='http://www.google.com'/>
  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' 
   href='http://www.google.com/books/feeds/volumes'/>
  <link rel='self' type='application/atom+xml' 
   href='http://www.google.com/books/feeds/volumes?q=php'/>
  <link rel='next' type='application/atom+xml' 
   href='http://www.google.com/books/feeds/volumes?q=php
   &start-index=11&max-results=10'/>
  <author>
    <name>Google Books Search</name>
    <uri>http://www.google.com</uri>
  </author>
  <generator version='beta'>Google Book Search data API</generator>
  <openSearch:totalResults>277</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>10</openSearch:itemsPerPage>
  <entry>
    <id>http://www.google.com/books/feeds/volumes/tywvv3ULal0C</id>
    <updated>2009-12-28T06:14:28.000Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind' 
      term='http://schemas.google.com/books/2008#volume'/>
    <title type='text'>Programming PHP</title>
    <link rel='http://schemas.google.com/books/2008/thumbnail' 
      type='image/x-unknown' href='http://bks8.books.google.com/books?
      id=tywvv3ULal0C&printsec=frontcover&img=1&zoom=5
      &edge=curl&sig=ACfU3U0WFIZOyvLPjIv7jqlX4XZ7GI4TAg
      &source=gbs_gdata'/>
    <link rel='http://schemas.google.com/books/2008/info' type='text/html' 
     href='http://books.google.com/books?id=tywvv3ULal0C&dq=php
     &ie=ISO-8859-1&source=gbs_gdata'/>
    <link rel='http://schemas.google.com/books/2008/preview' type='text/html' 
     href='http://books.google.com/books?id=tywvv3ULal0C
     &printsec=frontcover&dq=php&ie=ISO-8859-1&cd=1
     &source=gbs_gdata'/>
    <link rel='http://schemas.google.com/books/2008/annotation' 
     type='application/atom+xml' 
     href='http://www.google.com/books/feeds/users/me/volumes'/>
    <link rel='alternate' type='text/html' 
     href='http://books.google.com/books?
     id=tywvv3ULal0C&dq=php&ie=ISO-8859-1'/>
    <link rel='self' type='application/atom+xml' 
     href='http://www.google.com/books/feeds/volumes/tywvv3ULal0C'/>
    <gbs:embeddability value='http://schemas.google.com/books/2008#embeddable'/>
    <gbs:openAccess value='http://schemas.google.com/books/2008#disabled'/>
    <gbs:viewability value='http://schemas.google.com/books/2008#view_partial'/>
    <dc:creator>Rasmus Lerdorf</dc:creator>
    <dc:creator>Kevin Tatroe</dc:creator>
    <dc:creator>Peter MacIntyre</dc:creator>
    <dc:date>2006</dc:date>
    <dc:description>With style tips and practical programming advice, 
     this book will help you become not just a PHP programmer, 
     but a &quot;good&quot; PHP programmer.</dc:description>
    <dc:format>521 pages</dc:format>
    <dc:format>book</dc:format>
    <dc:identifier>tywvv3ULal0C</dc:identifier>
    <dc:identifier>ISBN:0596006810</dc:identifier>
    <dc:identifier>ISBN:9780596006815</dc:identifier>
    <dc:publisher>O'Reilly Media, Inc.</dc:publisher>
    <dc:subject>Computers</dc:subject>
    <dc:title>Programming PHP</dc:title>
  </entry>
  <entry>
  ...
  </entry>
</feed>

この出力にざっと目を通して、主な要素を把握してください。

  • Google Book Search Data API は REST リクエストに対し、要求されたデータが含まれる Atom フィードで応答します。ほとんどの場合、最も外側にある <feed> 要素のなかには、結果セットの現在のページ、次のページ、前のページの URL が含まれる <link> 要素、そして検索の要約統計情報が含まれる <openSearch:> 要素があります。
  • 最も外側の <feed> 要素の内側には 1 つ以上の <entry> 要素があり、そのそれぞれが、検索クエリーと一致する書籍すなわち「ボリューム」を表します。各 <entry> 要素には、その要素が表す書籍に関する詳細情報 (タイトル、説明、出版日、著者、出版社など) が含まれます。さらに各 <entry> 要素には <link> 要素も含まれ、ここに、書籍の詳細情報、サムネール画像、プレビュー (可能な場合)、レビューおよび評価などを表示するための URL リンクが示されます。
  • 各エントリーに含まれる名前空間が指定された <dc:> 要素は特筆に値します。これらの要素は、情報のマークアップおよびアクセスを単純化するために DCMI (Dublin Core Metadata Initiative) が定義している再利用可能な標準要素に対応します。リスト 1 に示されているように、これらの要素のなかには書籍のタイトル、著者、出版社、サイズおよびページ数、ジャンル、ISBN 識別子などが含まれます。

すべての Google Book Search Data API 関数が、上記のように一般にアクセス可能になっているわけではありません。検索用の関数には認証なしでアクセスできますが、データを変更する他の関数 (レビューおよびラベルを追加する関数やユーザーのライブラリーに書籍を追加する関数など) にアクセスできるのは、有効な Google アカウントのユーザー名とパスワードを提供して認証されたユーザーに限られます。この記事には、一般にアクセス可能な関数の例と、そうでない関数の例を両方記載します。

ブック検索クエリーの実行

公開 REST API によって Google ブック検索の検索結果にアクセスする方法がわかったところで、これと同じことを PHP アプリケーションから行う方法について検討します。1 つの方法はもちろん、PHP の組み込み XML 処理拡張機能 (SimpleXML、DOM、または XMLReader) を使用して、Google ブック検索から返された XML フィードを構文解析し、関連する情報のフラグメントを抽出することです。しかしサイズの大きなフィードや、名前空間が指定された大量の情報を処理するとなると、この方法の使い勝手はそれほど良くありません。そこで、この記事では別の手段を使うことにします。それは、PHP アプリケーションに Google Data API を統合しようとしている開発者専用に設計された Zend Framework の Zend_Gdata クライアント・ライブラリーです。

Zend_Gdata ライブラリーは Zend Framework の一部としてダウンロードすることも、スタンドアロンのパッケージとしてダウンロードすることもできます (「参考文献」にリンクを記載)。このライブラリーには Google Book Search Data API を操作するための専用モジュールが組み込まれており、事前定義されたクラスとメソッドによってデータ・アクセスと認証を単純化することができます。このライブラリーはコミュニティーによってテストされた確かなコード・ベースをアプリケーションに提供するだけでなく、このライブラリーを使うことによって、XML ツリーをナビゲートしたり、カスタム名前空間を処理したりするなどのこまごまとした詳細ではなく、アプリケーションのコア機能に専念することができます。

リスト 2 に、Zend_Gdata クライアント・ライブラリーを使用して Google Book Search Data API による書籍の検索結果のフィードを取得し、構文解析する方法を説明します。

リスト 2. Zend_Gdata ライブラリーを使用して検索結果を取得する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // perform login 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
  $books = new Zend_Gdata_Books($client);

  // prepare and execute search query
  $query = new Zend_Gdata_Books_VolumeQuery;
  $query->setQuery(urlencode('robert crais'));
  $feed = $books->getVolumeFeed($query);  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Searching for book titles</title>
  </head>
  <body>
    
    <h2><?php echo $feed->title; ?></h2>
    <div>
    <?php echo $feed->totalResults; ?> result(s) found.
    </div>
  
    <div id="results")
      <ol>
        <?php foreach ($feed as $entry): ?>
        <li>      
          <?php echo $entry->getTitle(); ?>
        </li>      
        <?php endforeach; ?>
      </ol>  
    </div>  
    
  </body>
</html>

リスト 2 では、まず Zend のクラス・ライブラリーをロードし、それから Zend_Gdata_ClientLogin クラスのインスタンスを初期化しています。このクライアントには、Google ブック検索サービスとの間で認証接続を行うために必要なユーザー認証情報が提供されます。認証接続が確立されると、Zend_Gdata_Books クラスの新しいインスタンスが初期化され、以降の Google Book Search Data API とのやりとりでは一貫して、このクラスが制御ポイントとしての役割を果たします。

Zend_Gdata_Books クラスのメソッドのうち、最も使われる可能性が最も高いメソッドは、検索クエリーと一致する書籍のタイトルをフィードで返す getVolumeFeed() です。このメソッドには、Zend_Gdata_Books_VolumeQuery クラスの setQuery() メソッドによってクエリー・ストリングが設定された、構成済みの状態の Zend_Gdata_Books_VolumeQuery クラスのインスタンスが渡されます。getVolumeFeed() メソッドへのレスポンスはリスト 1 に表示されているような Atom フィードです。このフィードは自動的に構文解析されて、それぞれにフィード内の 1 つの <entry> を表す Zend_Gdata_Books_VolumeEntry オブジェクトの配列に変換されます。後は、この配列を繰り返し処理し、オブジェクトのプロパティーを使って各エントリーの詳細を取得して HTML ページに変換するだけのことです。

図 1 は、表示される出力の一例です。ここにはキーワード「robert crais」と一致するすべての書籍が一覧にされています。

図 1. 基本的な Google ブックス API 検索の結果
「robert+crais」を基準とした Google ブックス API 検索による 400 件の結果のうち、最初の 10 件が示されています。
「robert+crais」を基準とした Google ブックス API 検索による 400 件の結果のうち、最初の 10 件が示されています。

この基本を理解できていれば、リスト 2 を変更して、簡単に対話性を向上させることができます。例えばリスト 3 では検索フォームを追加して、ユーザーが指定した書籍の検索クエリーを実行できるようにしています。

リスト 3. ユーザー指定のキーワードと一致する検索結果を取得する
<?php
if (isset($_POST['submit'])) {
  // load Zend Gdata libraries
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata_Books');
  Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
  
  // set credentials for ClientLogin authentication
  $user = "xxx@gmail.com";
  $pass = "secret";
  
  try {
    // perform login 
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'print');
    $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
    $books = new Zend_Gdata_Books($client);
  
    // prepare and execute search query
    $query = new Zend_Gdata_Books_VolumeQuery;
    $query->setQuery(urlencode($_POST['q']));
    $feed = $books->getVolumeFeed($query);  
  } catch (Exception $e) {
    die('ERROR:' . $e->getMessage());  
  }
}
?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Searching for book titles</title>
  </head>
  <body>
    
    <h2>Search</h2>
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for: 
    <input type="text" name="q" value="<?php echo isset($_POST['q']) ? 
     $_POST['q'] : ''; ?>" />
    <input type="submit" name="submit" value="Go" />
    </form>
  
    <?php if (isset($feed)): ?>
    <h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
    <div>
    <?php echo $feed->totalResults; ?> result(s) found.
    </div>
  
    <div id="results")
      <ol>
        <?php foreach ($feed as $entry): ?>
        <li>      
          <a href="<?php echo $entry->getInfoLink()->getHref(); ?>">
          <?php echo $entry->getTitle(); ?></a>
        </li>      
        <?php endforeach; ?>
      </ol>  
    </div>  
    <?php endif; ?>
    
  </body>
</html>

図 2 は、「indian cooking」の検索によって生成された出力の一例です。

図 2. 基本的な Google ブックス API 検索の結果
「indian cooking」を検索語とした Google ブックス API 検索による 574 件の結果のうち、最初の 10 件が示されています。
「indian cooking」を検索語とした Google ブックス API 検索による 574 件の結果のうち、最初の 10 件が示されています。

リスト 3 ではまた、Zend_Gdata_Books_VolumeEntry::getInfoLink() メソッドを使って Google ブック検索 Web サイトの該当する書籍情報ページへのリンクを表示していることに気付いたのではないでしょうか。このリンクをクリックすると、ユーザーは書籍に関する詳しい説明とユーザー・レビューなどの情報が記載されたページにリダイレクトされます。図 3 は、このページの一例です。

図 3. 書籍の詳細ページ
Google ブックスの詳細ページに記載された、Dennis Lehane 著『Gone, baby, gone』の詳細および関連する書籍
Google ブックスの詳細ページに記載された、Dennis Lehane 著『Gone, baby, gone』の詳細および関連する書籍

もう 1 つ指摘しておく価値のある点は、Google Book Search Data API に渡すクエリー・ストリングは、URL エンコードされたストリングでなければならないことです。上記の 2 つのリストでは、どちらも PHP の urlencode() メソッドによってストリングを URL エンコードしています。

詳細な書籍情報の取得

リスト 1 で説明したように、Google Book Search Data API によって返されるボリューム・フィードには、書籍のタイトルの他にも、かなりの情報が含まれます。例えば著者と出版社の名前、ISBN 番号、ページ数、ジャンルなどです。Zend_Gdata_Books ではこのような情報がすべて一連のオブジェクトとして表現されるため、これらのオブジェクトに PHP スクリプトのなかでアクセスして操作することによって、さらなる情報に満ちた検索結果ページを作成できます。

その一例として、リスト 4 を見てください。

リスト 4. 書籍の詳細情報を取得する
<?php
if (isset($_POST['submit'])) {
  // load Zend Gdata libraries
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata_Books');
  Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
  
  // set credentials for ClientLogin authentication
  $user = "xxx@gmail.com";
  $pass = "secret";
  
  try {
    // perform login 
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'print');
    $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
    $books = new Zend_Gdata_Books($client);
  
    // prepare and execute search query
    $query = new Zend_Gdata_Books_VolumeQuery;
    $query->setQuery(urlencode($_POST['q']));
    $feed = $books->getVolumeFeed($query);  
  } catch (Exception $e) {
    die('ERROR:' . $e->getMessage());  
  }
}
?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Searching for book titles</title>
    <style>
    .entry {
      height: 120px;
      border-bottom: dashed silver 2px;
      padding-top: 10px;
    }
    
    .thumbnail {
      float: left;  
      border: solid black 2px;
      padding: 2px;
      margin-right: 10px;
    }
    
    .desc {
      font-style: italic;  
    }
    
    .small {
      font-size: smaller;  
    }    
    </style>    
  </head>
  <body>
    
    <h2>Search</h2>
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Search for: 
    <input type="text" name="q" value="<?php echo isset($_POST['q']) ? 
     $_POST['q'] : ''; ?>" />
    <input type="submit" name="submit" value="Go" />
    </form>
  
    <?php if (isset($feed)): ?>
      <h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
      <div>
      <?php echo $feed->totalResults; ?> result(s) found.
      </div>
    
      <div id="results">
      <?php $x = 1; ?>
      <?php foreach ($feed as $entry): ?>
    
        <?php    
        //print_r($entry);   
        $book = new stdClass;
        
        // get title
        if (is_array($entry->getTitles())) {
          foreach ($entry->getTitles() as $title) {
            $book->titles[] = $title->getText(); 
          }
        }
        
        // get authors
        if (is_array($entry->getCreators())) {
          foreach ($entry->getCreators() as $creator) {
            $book->authors[] = $creator->getText(); 
          }
        }
    
        // get publishers
        if (is_array($entry->getPublishers())) {
          foreach ($entry->getPublishers() as $publisher) {
            $book->publishers[] = $publisher->getText(); 
          }
        }
        
        // get publication date
        if (is_array($entry->getDates())) {
          $arr = $entry->getDates();
          $book->pubdate = (is_object($arr[0])) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }
    
        // get ISBN numbers
        if (is_array($entry->getIdentifiers())) {
          foreach ($entry->getIdentifiers() as $id) {
            if (preg_match('/ISBN/', $id->getText())) {
              $book->isbn[] = $id->getText(); 
            }  
          }
        }
        
        // get first subject
        if (is_array($entry->getSubjects())) {
          $arr = $entry->getSubjects();
          $book->subject = is_object($arr[0]) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }
        
        // get first description
        if (is_array($entry->getDescriptions())) {
          $arr = $entry->getDescriptions();
          $book->desc = is_object($arr[0]) ? 
           $arr[0]->getText() : 'No description available'; 
        }            
        ?>
      
        <div class="entry">
          <div class="thumbnail">
            <img src="<?php echo ($entry->getThumbnailLink()) ? 
             $entry->getThumbnailLink()->getHref() : ''; ?>" />      
          </div>
          <div class="data">
          <?php echo $x; ?>. <?php echo ucwords(@implode(': ', 
           $book->titles)); ?><br/>
          <?php echo @implode(', ', $book->authors); ?> |
          <?php echo @implode(', ', $book->publishers); ?> |
          <?php echo $book->subject; ?> |
          <?php echo date('d M Y', strtotime($book->pubdate)); ?> <br/>
          <span class="desc"><?php echo $book->desc; ?></span> <br/>
          <span class="small"><?php echo @implode(', ', $book->isbn); ?> |       
            <a href="<?php echo $entry->getInfoLink()->getHref(); ?>">
            More information</a>   
          </span>
          </div>
        </div>      
        <?php $x++; ?>
      <?php endforeach; ?>
    <?php endif; ?>
    
  </body>
</html>

リスト 4 には、Zend_Gdata_Books_VolumeEntry クラスの新しいメソッドがいくつも導入されています。そのうち重要なメソッドについて、以下に簡単に説明します。

  • getDates() メソッドは書籍の出版日を返します。
  • getCreators() メソッドは書籍の著者の名前を返します。
  • getPublishers() メソッドは書籍の出版社の名前を返します。
  • getSubjects() および getDescriptions() メソッドはそれぞれ書籍のジャンル、書籍の説明を返します。
  • getTitles() メソッドは書籍のタイトル (およびサブタイトルがある場合はそのサブタイトル) を返します。
  • getIdentifiers() メソッドは書籍の ISBN-10 番号と ISBN-13 番号ならびに Google ブック検索のレコード ID からなる配列を返します。
  • getThumbnailLink() メソッドは書籍の表紙のサムネール画像の URL を返します。
  • getVolumeId() メソッドは Google ブック検索サービス内で一意に決まる書籍のボリューム識別子を返します。

これらのメソッドはいずれも、各種の Dublin Core メタデータ要素に対応したオブジェクトの配列を返します。配列が返された後は、開発者が随意、各配列の要素にアクセスし、その要素に含まれる情報を使って検索結果を構成し直すことができます。図 4 に、結果の一例を示します。

図 4. 検索結果に表紙の画像と書籍の追加データが含まれるように拡張した Google ブックス API 検索の結果
表紙の画像と書籍の追加データが含まれるように拡張した Google ブックス API 検索による 2 件の結果
表紙の画像と書籍の追加データが含まれるように拡張した Google ブックス API 検索による 2 件の結果

クエリー・フィルターの使用

もうお気付きかもしれませんが、これまでの例では、いずれの検索結果のフィードにも 10 件のエントリーしか含まれていませんでした。<openSearch:> 要素が実際にはそれよりも遥かに多い一致件数を示しているとしても、やはりフィードに含まれるエントリーは 10 件だけです。これは、Google ブック検索では各フィードに含める一致件数がデフォルトで 10 に制限されるためです。このデフォルト数は決して変更できないわけではありません。以下のパラメーターのいくつかを REST クエリーに追加することによって、API の出力を簡単にカスタマイズすることができます。

  • start-index パラメーター。フィードに含めるエントリーの開始オフセットを指定します。
  • max-results パラメーター。フィードに含めるエントリー数を指定します。
  • min-viewability パラメーター。部分的なプレビューまたは完全なプレビューが公開されている書籍のエントリーのみをフィードに含めるかどうかを指定します。

上記のパラメーターに加え、検索クエリーにフィルターを追加して、タイトル、著者、出版社、言語、ジャンル、説明、あるいは ISBN 番号を基準に書籍を検索することもできます。リスト 5 は、フィルターを追加する場合の一例です。

リスト 5. 著者、タイトル、および公開レベルを基準に検索結果をフィルタリングする
<?php
if (isset($_POST['submit'])) {
  // load Zend Gdata libraries
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata_Books');
  Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
  
  // set credentials for ClientLogin authentication
  $user = "xxx@gmail.com";
  $pass = "secret";
  
  try {
    // perform login 
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'print');
    $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
    $books = new Zend_Gdata_Books($client);
  
    // prepare and execute search query
    $query = new Zend_Gdata_Books_VolumeQuery;
    $queryStr = '';
    if (!empty($_POST['title'])) {
      $queryStr .= '+intitle:'.urlencode($_POST['title']);
    }
    if (!empty($_POST['author'])) {
      $queryStr .= '+inauthor:'.urlencode($_POST['author']);
    }    
    $query->setQuery($queryStr);
    $query->setMinViewability($_POST['v']);
    $query->setMaxResults(20);
    
    $feed = $books->getVolumeFeed($query);  
  } catch (Exception $e) {
    die('ERROR:' . $e->getMessage());  
  }
}
?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Searching for book titles</title>
    <style>
    .entry {
      height: 120px;
      border-bottom: dashed silver 2px;
      padding-top: 10px;
    }
    
    .thumbnail {
      float: left;  
      border: solid black 2px;
      padding: 2px;
      margin-right: 10px;
    }
    
    .desc {
      font-style: italic;  
    }
    
    .small {
      font-size: smaller;  
    }    
    </style>    
  </head>
  <body>
    
    <h2>Search</h2>
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    Title: 
    <input type="text" name="title" value="<?php echo isset($_POST['title']) ? 
     $_POST['title'] : ''; ?>" />
    
    Author: 
    <input type="text" name="author" value="<?php echo isset($_POST['author']) ? 
     $_POST['author'] : ''; ?>" />

    Viewability:
    <select name="v">
      <option value="none">Any</option>
      <option value="partial_view">Partial</option>
      <option value="full_view">Full</option>
    </select>    

    <input type="submit" name="submit" value="Go" />
    </form>
  
    <?php if (isset($feed)): ?>
      <h2>Search results for '<?php echo $query->getQuery(); ?>'
      </h2>
      <div>
      <?php echo $feed->totalResults; ?> result(s) found.
      </div>
    
      <div id="results">
      <?php $x = 1; ?>
      <?php foreach ($feed as $entry): ?>
    
        <?php    
        //print_r($entry);   
        $book = new stdClass;
        
        // get title
        if (is_array($entry->getTitles())) {
          foreach ($entry->getTitles() as $title) {
            $book->titles[] = $title->getText(); 
          }
        }
        
        // get authors
        if (is_array($entry->getCreators())) {
          foreach ($entry->getCreators() as $creator) {
            $book->authors[] = $creator->getText(); 
          }
        }
    
        // get publishers
        if (is_array($entry->getPublishers())) {
          foreach ($entry->getPublishers() as $publisher) {
            $book->publishers[] = $publisher->getText(); 
          }
        }
        
        // get publication date
        if (is_array($entry->getDates())) {
          $arr = $entry->getDates();
          $book->pubdate = (is_object($arr[0])) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }
    
        // get ISBN numbers
        if (is_array($entry->getIdentifiers())) {
          foreach ($entry->getIdentifiers() as $id) {
            if (preg_match('/ISBN/', $id->getText())) {
              $book->isbn[] = $id->getText(); 
            }  
          }
        }
        
        // get first subject
        if (is_array($entry->getSubjects())) {
          $arr = $entry->getSubjects();
          $book->subject = is_object($arr[0]) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }
        
        // get first description
        if (is_array($entry->getDescriptions())) {
          $arr = $entry->getDescriptions();
          $book->desc = is_object($arr[0]) ? 
           $arr[0]->getText() : 'No description available'; 
        }            
        ?>
      
        <div class="entry">
          <div class="thumbnail">
            <img src="<?php echo ($entry->getThumbnailLink()) ? 
             $entry->getThumbnailLink()->getHref() : ''; ?>" />      
          </div>
          <div class="data">
          <?php echo $x; ?>. <?php echo ucwords(@implode(': ', 
           $book->titles)); ?><br/>
          <?php echo @implode(', ', $book->authors); ?> |
          <?php echo @implode(', ', $book->publishers); ?> |
          <?php echo $book->subject; ?> |
          <?php echo date('d M Y', strtotime($book->pubdate)); ?> <br/>
          <span class="desc"><?php echo $book->desc; ?></span> 
          <br/>
          <span class="small"><?php echo @implode(', ', $book->isbn); ?> |       
            <a href="<?php echo $entry->getInfoLink()->getHref(); ?>">
            More information</a>   
          </span>
          </div>
        </div>      
        <?php $x++; ?>
      <?php endforeach; ?>
    <?php endif; ?>
    
  </body>
</html>

上記はリスト 4 の改定版で、タイトル、著者、公開レベルそれぞれの検索フィールドが表示されます。受け取った入力に応じて、該当する修飾子を設定した検索クエリーが作成され、Google Book Search API に送信されます。setMinViewability() および setMaxResults() メソッドに注目してください。この 2 つのメソッドが、それぞれ min-viewability 入力パラメーター、max-results 入力パラメーターに対するオブジェクト指向のインターフェースを提供します。

図 5図 6リスト 5 の出力を示します。前者の出力にはタイトルで検索した結果が表示されており、後者の出力には著者とタイトルを組み合わせた検索結果が表示されています。

図 5. タイトルでフィルタリングされた Google ブックス API 検索の結果
「+intitle:php」でフィルタリングした Google ブックス API 検索による 310 件の結果のうち、2 件が表示されています。
「+intitle:php」でフィルタリングした Google ブックス API 検索による 310 件の結果のうち、2 件が表示されています。
図 6. 著者とタイトルの名前でフィルタリングされた Google ブックス API 検索の結果
「+intitle:php+inauthor:vikram+vaswani」でフィルタリングした Google ブックス API 検索による 10 件の結果のうち、2 件が示されています。
「+intitle:php+inauthor:vikram+vaswani」でフィルタリングした Google ブックス API 検索による 10 件の結果のうち、2 件が示されています。

ユーザー・ライブラリーへのアクセス

Google ブック検索は一般の人々が検索を利用できるようにしている他、認証済みのユーザーに対しては、独自の仮想書籍ライブラリーを作成できるようにしています。この「マイライブラリ」機能では、ユーザーが書籍にレビューやラベルを付けたり、書籍のコレクションを作成して他のユーザーと共有したりできます。Google ブック検索の他の機能と同じく、この機能は Google Book Search Data API を介して使用できます。

「マイライブラリ」が機能する仕組みを調べるには、自分の Google アカウントで Google ブック検索にログインし、検索語を入力して各検索結果の隣に表示された「マイライブラリに追加」リンクをクリックします。これで、仮想ライブラリーの作成が始まります。このライブラリーには、各ページの右上隅に表示された「マイライブラリ」リンクを使って随時アクセスできます。図 7 は、ユーザー・ライブラリーの一例です。

図 7. Google ブックス Web サイト上のユーザー・ライブラリー
3 冊の書籍とそれぞれの表紙のサムネールおよび詳細が示されている、Google ブックス Web サイト上のユーザー・ライブラリーです。
3 冊の書籍とそれぞれの表紙のサムネールおよび詳細が示されている、Google ブックス Web サイト上のユーザー・ライブラリーです。

認証済みユーザーのライブラリーのコンテンツは、PHP アプリケーションでの構文解析に適した Atom フィードとして取得することもできます。リスト 1 で説明したボリューム・フィードと同じように、このフィードにも一連の <entry> 要素が含まれ、そのそれぞれがユーザーのライブラリーに含まれる書籍を表します。このフィードは、Zend_Gdata_Books オブジェクトの getUserLibraryFeed() メソッドによって一連の PHP オブジェクトに構文解析することができます。そうすれば、これらの PHP オブジェクトを使ってライブラリーの HTML ビューを生成することができます。リスト 6 にその方法を示します。

リスト 6. ユーザー・ライブラリーのコンテンツを取得する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // perform login 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
  $books = new Zend_Gdata_Books($client);

  // get authenticated user's library feed
  $feed = $books->getUserLibraryFeed();
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Displaying a user's library</title>
    <style>
    .entry {
      height: 120px;
      border-bottom: dashed silver 2px;
      padding-top: 10px;
    }
    
    .thumbnail {
      float: left;  
      border: solid black 2px;
      padding: 2px;
      margin-right: 10px;
    }
    
    .desc {
      font-style: italic;  
    }
    
    .small {
      font-size: smaller;  
    }    
    </style>    
  </head>
  <body>    
    <?php if (isset($feed)): ?>
      <h2>My Library</h2>
      <div>
      <?php echo $feed->totalResults; ?> result(s) found.
      </div>
    
      <div id="results">
      <?php $x = 1; ?>
      <?php foreach ($feed as $entry): ?>
    
      <?php    
      $book = new stdClass;
      
      // get title
      if (is_array($entry->getTitles())) {
        foreach ($entry->getTitles() as $title) {
          $book->titles[] = $title->getText(); 
        }
      }
      
      // get authors
      if (is_array($entry->getCreators())) {
        foreach ($entry->getCreators() as $creator) {
          $book->authors[] = $creator->getText(); 
        }
      }
  
      // get publishers
      if (is_array($entry->getPublishers())) {
        foreach ($entry->getPublishers() as $publisher) {
          $book->publishers[] = $publisher->getText(); 
        }
      }
      
      // get publication date
      if (is_array($entry->getDates())) {
        $arr = $entry->getDates();
        $book->pubdate = (is_object($arr[0])) ? 
         $arr[0]->getText() : 'Unspecified'; 
      }
  
      // get ISBN numbers
      if (is_array($entry->getIdentifiers())) {
        foreach ($entry->getIdentifiers() as $id) {
          if (preg_match('/ISBN/', $id->getText())) {
            $book->isbn[] = $id->getText(); 
          }  
        }
      }
      
      // get first subject
      if (is_array($entry->getSubjects())) {
        $arr = $entry->getSubjects();
        $book->subject = is_object($arr[0]) ? 
         $arr[0]->getText() : 'Unspecified'; 
      }
      
      // get first description
      if (is_array($entry->getDescriptions())) {
        $arr = $entry->getDescriptions();
        $book->desc = is_object($arr[0]) ? 
         $arr[0]->getText() : 'No description available'; 
      }    
      ?>
      
        <div class="entry">
          <div class="thumbnail">
            <img src="<?php echo ($entry->getThumbnailLink()) ? 
             $entry->getThumbnailLink()->getHref() : ''; ?>" />      
          </div>
          <div class="data">
          <?php echo $x; ?>. <?php echo ucwords(@implode(': ', 
           $book->titles)); ?><br/>
          <?php echo @implode(', ', $book->authors); ?> |
          <?php echo @implode(', ', $book->publishers); ?> |
          <?php echo $book->subject; ?> |
          <?php echo date('d M Y', strtotime($book->pubdate)); ?> <br/>
            <span class="desc"><?php echo $book->desc; ?></span> 
            <br/>
            <span class="small"><?php echo @implode(', ', $book->isbn); ?> |       
              Added to library on: <?php echo ($entry->getPublished()) ? 
              date('d M Y', strtotime($entry->getPublished()->getText())) : ''; 
              ?> | 
              <a href="<?php echo $entry->getInfoLink()->getHref(); ?>"
               >More information</a>  
            </span>
          </div>
        </div>      
        <?php $x++; ?>
      <?php endforeach; ?>
    <?php endif; ?>
    
  </body>
</html>

上記のスクリプトの大部分は、これまでのセクションでもうお馴染みのはずです。このスクリプトは Google ブック検索サービスとの認証接続を開始し、Zend_Gdata_Books オブジェクトを初期化してから、getUserLibraryFeed() メソッドを使ってユーザー・ライブラリーに含まれる書籍のリストが含まれるフィードを取得します。このフィードは PHP オブジェクトの配列として表現されるので、後は、配列を繰り返し処理して各エントリーを処理し、適切な HTML マークアップを使用して結果を表示するだけの話です。

図 8 に、結果の一例を示します。

図 8. ユーザーのライブラリー・フィードを要求する Google ブックス API リクエストの結果
ユーザーのライブラリー・フィードを要求する Google ブックス API リクエストの結果として、3 冊の書籍がそれぞれの表紙のサムネールと書籍の説明とともに表示されています。
ユーザーのライブラリー・フィードを要求する Google ブックス API リクエストの結果として、3 冊の書籍がそれぞれの表紙のサムネールと書籍の説明とともに表示されています。

ユーザー・ライブラリーへの書籍の追加

ユーザー・ライブラリーのコンテンツは取得できるようになりましたが、新しい書籍をライブラリーに追加する場合はどうすればよいのでしょうか。それには一意に決まる書籍のボリューム識別子を含めた <entry> を XML にエンコードし、Google Book Search Data API を使ってユーザー・ライブラリーのフィードに送信すればよいだけです。リスト 7 に、その場合の POST リクエストの一例を記載します。

リスト 7. ユーザーのライブラリーに書籍を追加する場合の POST リクエストの例
POST /books/feeds/users/me/collections/library/volumes HTTP/1.1
Host: books.google.com
Connection: close
User-Agent: MyCompany-MyApp-1.0 Zend_Framework_Gdata/1.9.0
authorization: GoogleLogin 
Content-Type: application/atom+xml
Accept-encoding: identity
Content-Length: 97

<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:id>BOOK_VOLUME_ID_HERE</atom:id>
</atom:entry>

これと同じ操作を Zend_Gdata_Books で実行するには、新規 Zend_Gdata_Books_VolumeEntry オブジェクトを初期化してボリューム識別子を割り当てた上で、insertVolume() メソッドを使用して、そのオブジェクトをユーザー・ライブラリーのフィードに追加します。このコードをリスト 8 に記載します。

リスト 8. ユーザーのライブラリーに書籍を追加する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // perform login 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $books = new Zend_Gdata_Books($client);

  // add book to user's library using volume ID
  $id = 'BOOK_VOLUME_ID_HERE';
  $entry = new Zend_Gdata_Books_VolumeEntry();
  $entry->setId(new Zend_Gdata_App_Extension_Id($id));
  $books->insertVolume(
      $entry,
      Zend_Gdata_Books::MY_LIBRARY_FEED_URI
  );
    
  // display success message
  echo "Volume added successfully with ID: $id";  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

書籍のレビューおよびラベルの追加

Google Book Search API ではユーザーが自分たちのライブラリーに書籍を追加できるだけでなく、書籍にレビューやラベルを追加することもできます。レビューとラベルは Google が「注釈」と呼んでいるものとして保存されます。リスト 1 をもう一度見てみると、すべてのエントリーに注釈 URL が含まれていることがわかります。したがって、書籍にレビューやラベルを追加するには、XML にエンコードされた <entry> をその書籍用に作成し、そのエントリーにレビューやラベルを追加してから POST リクエストで書籍の注釈 URL に送信するだけでよいのです。

リスト 9 に、その場合の POST リクエストの一例を記載します。

リスト 9. 書籍のレビューを追加する場合の POST リクエストの例
POST /books/feeds/users/me/volumes HTTP/1.1
Host: www.google.com
Connection: close
User-Agent: MyCompany-MyApp-1.0 Zend_Framework_Gdata/1.9.0
authorization: GoogleLogin 
Accept-encoding: identity
Content-Type: application/atom+xml
Content-Length: 3291

<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
  <openAccess xmlns="http://schemas.google.com/books/2008" 
   value="http://schemas.google.com/books/2008#disabled"/>
  <atom:category term="http://schemas.google.com/books/2008#volume" 
   scheme="http://schemas.google.com/g/2005#kind"/>
  <atom:id>http://www.google.com/books/feeds/volumes/BOOK_VOLUME_ID_HERE
   </atom:id>
  <atom:link href="http://bks7.books.google.com/books?id=BOOK_VOLUME_ID_HERE
   &printsec=frontcover&img=1&zoom=5&sig=ACfU3U0ayCK47roiq
   7r_hf_Iy-tQ&source=gbs_gdata" 
   rel="http://schemas.google.com/books/2008/thumbnail" type="image/x-unknown"/>
  <atom:link href="http://books.google.com/books?id=BOOK_VOLUME_ID_HERE
   &ie=ISO-8859-1&source=gbs_gdata" 
   rel="http://schemas.google.com/books/2008/info" type="text/html"/>
  <atom:link href="http://www.google.com/books/feeds/users/me/volumes" 
   rel="http://schemas.google.com/books/2008/annotation" 
   type="application/atom+xml"/>
  <atom:link href="http://books.google.com/books?id=BOOK_VOLUME_ID_HERE
   &ie=ISO-8859-1" rel="alternate" type="text/html"/>
  <atom:link href="http://www.google.com/books/feeds/volumes/BOOK_VOLUME_ID_HERE" 
   rel="self" type="application/atom+xml"/>
  <atom:title type="text">The Two Minute Rule</atom:title>
  <atom:updated>2009-12-28T10:15:44.000Z</atom:updated>
  <dc:creator xmlns:dc="http://purl.org/dc/terms">Robert Crais</dc:creator>
  <dc:date xmlns:dc="http://purl.org/dc/terms">2006-01-01</dc:date>
  <dc:format xmlns:dc="http://purl.org/dc/terms">Dimensions 10.8x17.2x3.0 cm
  </dc:format>
  <dc:format xmlns:dc="http://purl.org/dc/terms">465 pages</dc:format>
  <dc:format xmlns:dc="http://purl.org/dc/terms">book</dc:format>
  <dc:identifier xmlns:dc="http://purl.org/dc/terms">BOOK_VOLUME_ID_HERE
  </dc:identifier>
  <dc:identifier xmlns:dc="http://purl.org/dc/terms">ISBN:1111111111
  </dc:identifier>
  <dc:identifier xmlns:dc="http://purl.org/dc/terms">ISBN:1111111111111
  </dc:identifier>
  <dc:language xmlns:dc="http://purl.org/dc/terms">en</dc:language>
  <dc:publisher xmlns:dc="http://purl.org/dc/terms">Pocket Books
  </dc:publisher>
  <dc:subject xmlns:dc="http://purl.org/dc/terms">Fiction / Action & Adventure
  </dc:subject>
  <dc:subject xmlns:dc="http://purl.org/dc/terms">Fiction / Suspense
  </dc:subject>
  <dc:subject xmlns:dc="http://purl.org/dc/terms">Fiction / Action & Adventure
  </dc:subject>
  <dc:title xmlns:dc="http://purl.org/dc/terms">The Two Minute Rule
  </dc:title>
  <gbs:embeddability xmlns:gbs="http://schemas.google.com/books/2008" 
   value="http://schemas.google.com/books/2008#not_embeddable"/>
  <gd:rating xmlns:gd="http://schemas.google.com/g/2005" min="1" max="5" 
   average="4.20"/>
  <gbs:review xmlns:gbs="http://schemas.google.com/books/2008">
   This book is amazing - v!</gbs:review>
  <gbs:viewability xmlns:gbs="http://schemas.google.com/books/2008" 
   value="http://schemas.google.com/books/2008#view_no_pages"/>
</atom:entry>

リスト 10 は、対象とする書籍のボリューム識別子と Zend_Gdata ライブラリーを使用してレビューを送信する例です。

リスト 10. 書籍のレビューを追加する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // perform login 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $books = new Zend_Gdata_Books($client);

  // add review to book
  $id = 'BOOK_VOLUME_ID_HERE';  
  $entry = $books->getVolumeEntry($id);
  $review = new Zend_Gdata_Books_Extension_Review();
  $review->setText("This book is amazing - v!");
  $entry->setReview($review);  
  $books->insertVolume(
      $entry,
      $entry->getAnnotationLink()->getHref()
  );  
  
  // display success message
  echo "Review successfully added with ID: $id";  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

リスト 10 では getVolumeEntry() メソッドで書籍のボリューム識別子を使用して書籍に対応する現行エントリーを取得し、次に setReview() メソッドを使って、レビューのテキストが含まれる Zend_Gdata_Books_Extension_Review オブジェクトをエントリーに追加しています。その後は、insertVolume() メソッドが POST リクエストの作成から Google サーバーでのエントリー更新まで引き受けてくれます。

同じように、Google ブック検索ではユーザーが各書籍に記述的なキーワードのタグ、つまり「ラベル」を付けることも可能です。ラベル付けはコミュニティーのための便利な機能で、これによって一層効率的かつ関連性の高い検索結果をもたらすことができます。リスト 11 は、プログラムによって書籍エントリーにラベルを追加する例です。

リスト 11. 書籍のラベルを追加する
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// set credentials for ClientLogin authentication
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // perform login 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $books = new Zend_Gdata_Books($client);

  // add labels to book
  $id = 'BOOK_VOLUME_ID_HERE';  
  $entry = $books->getVolumeEntry($id);
  $entry->setCategory(array(
    new Zend_Gdata_App_Extension_Category('crime', 
      'http://schemas.google.com/books/2008/labels'),
    new Zend_Gdata_App_Extension_Category('suspense', 
      'http://schemas.google.com/books/2008/labels'),
    new Zend_Gdata_App_Extension_Category('elvis cole', 
      'http://schemas.google.com/books/2008/labels')
  ));  
  $books->insertVolume(
      $entry,
      $entry->getAnnotationLink()->getHref()
  );  
  
  // display success message
  echo "Labels successfully added for ID: $id";  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

リスト 11 では、各ラベルは Zend_Gdata_App_Extension_Category インスタンスとして表されています。これらのインスタンスが setCategory() メソッドによって書籍エントリーに追加されると、続いて insertVolume() メソッドが呼び出され、このメソッドによって Google ブック検索データベース内の書籍にラベルが追加されます。

Google ブック検索に追加されるレビューおよびラベルは非公開ではないので、インターネット・ユーザーの誰もが、Google ブックス Web サイトや公開フィード URL を使って表示することができます。例えば、ある特定のユーザーが作成したレビューとラベルのすべてを表示するには、URL http://books.google.com/books/feeds/users/USER_ID/volumes を指定して、そのユーザーの注釈フィードにアクセスします。注意する点として、この URL に含める USER_ID は、Google ブック検索でのユーザー固有の ID であり、Google アカウントのユーザー名ではありません。Google ブック検索でのユーザー ID は、そのユーザーの「マイライブラリ」URL リンクを見るとわかります。

まとめ

Google Book Search Data API は現在も開発中ですが、開発者が書籍の検索結果を Web アプリケーションに統合する上で、非常に大きな可能性を提供します。この記事では、Google ブック検索のボリューム・フィードの例や、キーワード、著者、タイトルを基準に書籍を検索する方法、そして検索結果のフィードから書籍のメタデータ (出版社と著者の情報)、サムネール画像、ISBN 番号を抽出する方法を説明しました。さらに、Google ブック検索が提供するコミュニティーのための機能を短時間で習得してもらえるように、プログラムによって書籍エントリーにレビューおよびラベルを追加する方法を説明しました。

これらの例から明らかなように、開発者が新しい Web アプリケーションを作成する際に大幅な柔軟性と自由をもたらしてくれる Google Book Search REST API は、書籍検索のデータを他の Web サービスのデータとマッシュアップする際にも、あるいはただ単に著者や出版社、または消費者向けにカスタマイズした検索インターフェースを作成する際にも大活躍します。ぜひ、この API を実際に使って確かめてみてください。


ダウンロード可能なリソース


関連トピック

  • Developer's Guide および Reference Guide: Google Book Search API の詳細を学んでください。
  • Google ブック検索のブログ: Google ブックス API に関するニュースを調べてください。
  • Google アカウント: 自分自身のアカウントを登録してください。
  • Google ブック検索のフォーラム: Google Book Search API 開発についてのディスカッションを読んで、参加してください。
  • Zend_Gdata_Books ライブラリー: Zend Framework の詳細と、Google Book Search Data API でこのライブラリーを使用する方法について読んでください。
  • Dublin Core Metadata Initiative: 広範な用途とビジネス・モデルをサポートする相互運用可能なメタデータ標準について学んでください。
  • この著者による他の記事 (Vikram Vaswani 著、developerWorks、2007年8月から現在まで): XML や Google Book Search Data API 以外の Google API、そしてその他の技術に関する記事を読んでください。
  • developerWorks の XML エリア: XML 分野でのスキルを磨くための資料を入手してください。
  • IBM XML 認定: XML や関連技術の IBM 認定技術者になる方法について調べてください。
  • developerWorks podcasts: ソフトウェア開発者向けの興味深いインタビューとディスカッションを聞いてください。
  • Zend Gdata Client Library: このクライアント・ライブラリーをダウンロードして、PHP 5 アプリケーションから Google の Data API にアクセスするために必要なすべてのものを入手してください。
  • IBM 製品の評価版: DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を体験するには、評価版をダウンロードするか、IBM SOA Sandbox のオンライン試用版を試してみてください。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Open source, Web development
ArticleID=465907
ArticleTitle=Google ブック検索を PHP アプリケーションに統合する
publish-date=01072010