Интеграция службы поиска книг Google в PHP-приложение

Использование PHP для обработки и интеграции данных из Google Book Search с помощью специального Web-приложения

Служба поиска книг Google Books позволяет разработчикам Web-приложений получать списки книг и метаданных через API на базе архитектуры REST. Модуль Gdata среды Zend Framework предоставляет возможность обрабатывать XML-каналы, генерируемые этим API, и использовать его в контексте настраиваемых Web-приложений. Эта статья знакомит читателя с API данных Google Book Search, демонстрируя, как его можно использовать для поиска книг по ключевым словам, автору и названию; получать эскизы обложек и анонсы, а также добавлять отзывы и библиографические данные в библиотеки пользователей.

Введение

Часто используемые сокращения

  • API: Application programming interface
  • DOM: Document Object Model
  • HTTP: Hypertext Transfer Protocol
  • HTML: Hypertext Markup Language
  • ISBN: International Standard Book Number
  • REST: Representational state transfer
  • URL: Uniform Resource Locator
  • XML: Extensible Markup Language

Если вы так или иначе связаны с издательской индустрией, или даже если вы просто заядлый читатель, вы, вероятно, уже слышали о службе Google Books. Это попытка Google создать крупнейшую в мире цифровую библиотеку с функциями поиска, отсканировав миллионы книг, и сделать их доступными для ознакомления и приобретения в Интернете. It's also one of Google's most controversial projects, the focus of a class action lawsuit that was only recently settled in November 2009.

Служба Google Books интересна не только для читателя, но и с точки зрения разработчика – своим API данных. Этот API позволяет выполнять чтение и поиск в базе данных Google Books тех книг, которые соответствуют заданным пользователем критериям, и применять результаты этого поиска в других Web-приложениях. Доступ к этому API, который следует модели REST, можно получить с помощью любого инструментария разработки, поддерживающего XML. У этого API уже есть клиентские библиотеки для PHP, Java™ и других распространенных языков программирования.

В этой статье мы познакомим вас с API данных Google Book и покажем, как интегрировать и использовать результаты поиска книг со специально разработанным PHP-приложением. Она содержит примеры поиска книг по ключевым словам, по языку или по автору; извлечения библиографических данных (в том числе номеров ISBN и эскизов обложек), а также добавления отзывов и оценок по тем книгам, которые уже включены в базу данных. Итак, приступим!


Как работают каналы поиска книг

Прежде чем приступить к созданию PHP-кода, будет уместно сказать несколько слов об API данных Google Book Search. Как и все службы, базирующиеся на REST, API принимает запросы HTTP, содержащие один или несколько входных аргументов на языке XML, и возвращает XML-ответы, которые можно обрабатывать в любой клиентской программе, поддерживающей XML. В API данных Google Book Search ответ всегда представляет собой канал Atom, содержащий запрашиваемую информацию.

Типичный канал Book Search содержит более чем достаточную информацию для создания полезного и адекватного приложения. Чтобы убедиться в этом, попробуйте навести Web-браузер на URL http://books.google.com/books/feeds/volumes?q=php. Этот метод REST возвращает список книг по ключевому слову php. Необработанный XML-ответ на этот метод (который можно увидеть в исходном коде страницы результатов) содержит подробную информацию об этих книгах и может выглядеть примерно так, как показано в листинге 1.

Листинг 1. Пример канала Google Book Search
<?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>

Пройдемся беглым взглядом по этому результату, чтобы ознакомиться с его основными элементами.

  • В ответ на запрос REST API данных Google Book Search возвращает канал Atom, содержащий запрошенные данные. В большинстве случаев внешний элемент <feed> содержит элементы <link> с указателями URL на текущую, следующую и предыдущую страницы набора результатов, а также элементы <openSearch:>, которые содержат краткую статистику поиска.
  • Внешний элемент <feed> содержит один или несколько элементов <entry>, каждый из которых представляет книгу или "том", соответствующий поисковому запросу. Каждый элемент <entry> содержит дополнительную информацию о книге, которую он представляет, в том числе название, описание, дату публикации, автора и издателя. Кроме того, в каждом элементе <entry> присутствуют элементы <link>, которые ссылаются на подробную информацию о книге, эскиз обложки, анонс (при его наличии), а также аннотации, такие как отзывы и оценки.
  • Особого упоминания достойны элементы каждой записи с пространствами имен <dc:>. Эти элементы соответствуют элементам проекта Dublin Core Metadata Initiative (DCMI), который предоставляет набор стандартных, многократно используемых определений для простой разметки информации и доступа к ней. Как иллюстрирует листинг 1, эти элементы содержат сведения о названии, авторах, издательстве, формате, теме и идентификаторах ISBN для каждой книги.

Не все функции API данных Google Book Search общедоступны. Если доступ к функциям поиска можно получить без аутентификации, то к другим функциям, которые изменяют данные (в том числе функциям добавления отзывов и меток или добавления книг в библиотеку пользователя), можно обращаться только в том случае, если вы являетесь авторизованным пользователем и можете указать действительные имя пользователя и пароль учетной записи Google. В этой статье мы рассмотрим примеры функций обоих типов.


Выполнение запросов поиска книг

Теперь, когда вы знаете, как получить доступ к результатам поиска книг Google в рамках общедоступного API REST, посмотрим, как сделать то же самое из PHP-приложения. Один из способов, конечно, заключается в применении встроенных в PHP расширений обработки XML (SimpleXML, DOM или XMLReader) для анализа XML-канала, возвращенного Google Book Search, и извлечении из него соответствующих фрагментов информации. Однако это не очень удобно, особенно если вы имеете дело с емкими каналами или большими объемами информации в пространствах имен. Поэтому в данной статье будет использоваться другой подход: Клиентская библиотека Zend_Gdata из Zend Framework, специально предназначенная для разработчиков, которые пытаются интегрировать PHP-приложения с Google Data API.

Библиотеку Zend_Gdata можно загрузить либо в составе Zend Framework, либо как отдельный пакет (см. ссылку в разделе Ресурсы). Она включает в себя специальный модуль для работы с API данных Google Book Search, обеспечивая готовые классы и методы для упрощения доступа к данным и аутентификации. Эта библиотека не только составит надежную, проверенную сообществом базу кода для вашего приложения, но и возможность сосредоточиться на основных функциях приложения, а не на деталях деревьев XML-навигации или обработки особых пространств имен.

Листинг 2 иллюстрирует, как использовать клиентскую библиотеку Zend_Gdata для извлечения и анализа результатов поиска книг с помощью API данных Google Book Search.

Листинг 2. Получение результатов поиска с применением библиотеки Zend_Gdata
<?php
// Загрузка библиотек Zend Gdata
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// Задание верительных данных для аутентификации ClientLogin
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // Регистрация 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
  $books = new Zend_Gdata_Books($client);

  // Подготовка и исполнение поискового запроса
  $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_Http_Client. Этот клиент снабжен учетными данными пользователя, необходимыми для создания соединения с проверкой подлинности со службой Google Book Search. После установки соединения инициализируется новый экземпляр класса Zend_Gdata_Books; этот класс служит центром управления всем последующим взаимодействием с API данных Google Book Search.

Наиболее подходящий метод Zend_Gdata_Books – это метод getVolumeFeed(), который возвращает список книг, соответствующих поисковому запросу. Этот метод передает экземпляр настроенного класса Zend_Gdata_Books_VolumeQuery со строкой запроса, которая задается методом класса setQuery(). Ответом на метод getVolumeFeed() служит канал Atom, аналогичный приведенному в листинге 1; этот канал обрабатываться автоматически и преобразуется в массив объектов Zend_Gdata_Books_VolumeEntry, каждый из которых представляет один элемент <entry> канала. Теперь легко перебрать этот массив, извлечь информацию о каждой записи с использованием свойств объекта и превратить его в страницы HTML.

На рисунке 1 демонстрируется возможный результат - список всех книг, соответствующих ключевому слову 'robert crais':

Рисунок 1. Результат простого поиска посредством API Google Books
Результат простого поиска посредством API Google Books 'robert+crais' shows first 10 of 400 results

Овладев этими основами, легко изменить листинг 2, сделав его более интерактивным. Листинг 3 демонстрирует, как добавить форму поиска, которую можно использовать для формирования запроса на поиск книг.

Листинг 3. Получение результатов поиска, соответствующих ключевым словам пользователя
<?php
if (isset($_POST['submit'])) {
  // Загрузка библиотек Zend Gdata
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata_Books');
  Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

  // Задание верительных данных для аутентификации ClientLogin
  $user = "xxx@gmail.com";
  $pass = "secret";

  try {
    // Регистрация 
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'print');
    $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
    $books = new Zend_Gdata_Books($client);

    // Подготовка и исполнение поискового запроса
    $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. Результат простого поиска посредством API Google Books
Результат простого поиска посредством API Google Books 'indian cooking' shows first 10 of 574 results

Вы заметите одно дополнение в листинге 3: использование метода Zend_Gdata_Books_VolumeEntry::getInfoLink(), который возвращает ссылку на страницу с информацией о книге на Web-сайте Google Book Search. При нажатии на эту ссылку пользователь будет перенаправлен на страницу, содержащую, среди прочего, подробное описание книги и отзывы читателей. На рисунке 3 приведен пример такой страницы:

Рисунок 3. Страница с информацией о книге
Страница с информацией о книге 'book Gone, baby, gone' by Dennis Lehane and related books

Стоит также отметить, что строка запроса, которая передается в API данных Google Book Search, должна иметь вид URL. Это делается так же, как в предыдущих листингах, с помощью метода РНР urlencode().


Получение подробной информации о книге

Как говорилось при обсуждении листинга 1, перечень томов, возвращаемый API данных Google Book Search, содержит достаточно информации помимо названия книги: имена автора и издателя, номер ISBN, число страниц, тему и так далее. С помощью Zend_Gdata_Books вся эта информация представляется в виде набора объектов, к которым можно получить доступ и манипулировать в рамках сценария PHP для создания более информативных страниц с результатами поиска.

В качестве примера рассмотрим листинг 4.

Листинг 4. Получение подробной информации о книге
<?php
if (isset($_POST['submit'])) {
  // Загрузка библиотек Zend Gdata
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata_Books');
  Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

  // Задание верительных данных для аутентификации ClientLogin
  $user = "xxx@gmail.com";
  $pass = "secret";

  try {
    // Регистрация 
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'print');
    $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
    $books = new Zend_Gdata_Books($client);

    // Подготовка и исполнение поискового запроса
    $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;

        // Получение названия
        if (is_array($entry->getTitles())) {
          foreach ($entry->getTitles() as $title) {
            $book->titles[] = $title->getText(); 
          }
        }

        // Получение авторов
        if (is_array($entry->getCreators())) {
          foreach ($entry->getCreators() as $creator) {
            $book->authors[] = $creator->getText(); 
          }
        }

        // Получение издателей
        if (is_array($entry->getPublishers())) {
          foreach ($entry->getPublishers() as $publisher) {
            $book->publishers[] = $publisher->getText(); 
          }
        }

        // Получение даты публикации
        if (is_array($entry->getDates())) {
          $arr = $entry->getDates();
          $book->pubdate = (is_object($arr[0])) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }

        // Получение номеров ISBN
        if (is_array($entry->getIdentifiers())) {
          foreach ($entry->getIdentifiers() as $id) {
            if (preg_match('/ISBN/', $id->getText())) {
              $book->isbn[] = $id->getText(); 
            }  
          }
        }

        // Получение первого предмета
        if (is_array($entry->getSubjects())) {
          $arr = $entry->getSubjects();
          $book->subject = is_object($arr[0]) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }

        // Получение первого описания
        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 Book Search;
  • метод getThumbnailLink() возвращает URL миниатюрного изображения обложки книги;
  • метод getVolumeId() возвращает уникальный идентификатор тома книги в службе Google Book Search.

Все эти методы возвращают массив объектов, соответствующих различным элементам метаданных Dublin Core; затем разработчику нужно обращаться к элементам каждого массива и использовать эту информацию для составления результата поиска. Рисунок 4 иллюстрирует пример такого результата.

Рисунок 4. Результат поиска API Google Books с добавленным изображением обложки и дополнительными библиографическими данными
Результат поиска API Google Books с добавленным изображением обложки и дополнительными библиографическими данными

Использование фильтров запросов

Вы могли заметить, что во всех предыдущих примерах результаты поиска содержат только по 10 записей, даже если элементы <openSearch:> свидетельствуют о гораздо большем числе совпадений. Причина в том, что по умолчанию каналы Google Book Search ограничены 10 совпадениями на канал. Это отнюдь не высечено из камня; выход API можно легко настроить, добавив к запросу REST некоторые из следующих параметров:

  • параметр start-index определяет начальное смещение для записей в канале;
  • параметр max-results определяет количество записей в канале;
  • параметр min-viewability определяет, будут ли записи канала включать только те книги, для которых существуют частичные или полные анонсы.

В дополнение к этим параметрам можно добавить фильтры поисковых запросов для поиска книг по названию, автору, издателю, языку, теме, описанию или номеру ISBN. Как это можно сделать, показано в листинге 5.

Листинг 5. Фильтрация результатов поиска по автору, названию и наличию анонса
<?php
if (isset($_POST['submit'])) {
  // Загрузка библиотек Zend Gdata
  require_once 'Zend/Loader.php';
  Zend_Loader::loadClass('Zend_Gdata_Books');
  Zend_Loader::loadClass('Zend_Gdata_Books_VolumeQuery');
  Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

  // Задание верительных данных для аутентификации ClientLogin
  $user = "xxx@gmail.com";
  $pass = "secret";

  try {
    // Регистрация 
    $client = Zend_Gdata_ClientLogin::getHttpClient(
      $user, $pass, 'print');
    $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
    $books = new Zend_Gdata_Books($client);

    // Подготовка и исполнение поискового запроса
    $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;

        // Получение названия
        if (is_array($entry->getTitles())) {
          foreach ($entry->getTitles() as $title) {
            $book->titles[] = $title->getText(); 
          }
        }

        // Получение авторов
        if (is_array($entry->getCreators())) {
          foreach ($entry->getCreators() as $creator) {
            $book->authors[] = $creator->getText(); 
          }
        }

        // Получение издателей
        if (is_array($entry->getPublishers())) {
          foreach ($entry->getPublishers() as $publisher) {
            $book->publishers[] = $publisher->getText(); 
          }
        }

        // Получение даты публикации
        if (is_array($entry->getDates())) {
          $arr = $entry->getDates();
          $book->pubdate = (is_object($arr[0])) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }

        // Получение номеров ISBN
        if (is_array($entry->getIdentifiers())) {
          foreach ($entry->getIdentifiers() as $id) {
            if (preg_match('/ISBN/', $id->getText())) {
              $book->isbn[] = $id->getText(); 
            }  
          }
        }

        // Получение первого предмета
        if (is_array($entry->getSubjects())) {
          $arr = $entry->getSubjects();
          $book->subject = is_object($arr[0]) ? 
           $arr[0]->getText() : 'Unspecified'; 
        }

        // Получение первого описания
        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 пользователю предоставляются отдельные поля для поиска по названию, автору и наличию анонса. В зависимости от полученных данных, поисковый запрос снабжается соответствующими модификаторами и передается в API Google Book Search. Обратите внимание на методы setMinViewability() и setMaxResults(), которые предоставляют объектно-ориентированный интерфейс для min-viewability ввода параметров max-results.

Рисунок 5 и рисунок 6 иллюстрируют результат выполнения кода из листинга 5, причем первый отображает результаты поиска по названию, а второй – по сочетанию автора и названия.

Рисунок 5. Результат поиска посредством API Google Books, отфильтрованный по названию
Результат поиска посредством API Google Books '+intitle:php'
Рисунок 6. Результат поиска посредством API Google Books, отфильтрованный по автору и названию
Результат поиска посредством API Google Books '+intitle:php+inauthor:vikram+vaswani'

Доступ к библиотекам пользователя

В дополнение к общедоступным возможностям поиска Google Book Search позволяет авторизованным пользователям создавать свои собственные виртуальные библиотеки. Эта функция "Моя библиотека" позволяет просматривать и помечать книги, а также создавать книжные собрания и обмениваться ими с другими пользователями. Как и другие функции Google Book Search, она доступна через API данных.

Чтобы увидеть, как работает функция "Моя библиотека", войдите в Google Book Search, используя учетную запись Google, введите ключ поиска и воспользуйтесь ссылкой "Добавить в библиотеку", которая появляется рядом с каждым результатом поиска, чтобы приступить к созданию виртуальной библиотеки. К этой библиотеке можно обращаться в любое время с помощью ссылки "My Library", которая появляется в верхнем правом углу каждой страницы. На рисунке 7 приведен пример одной из таких библиотек пользователей.

Рисунок 7. Библиотека пользователя на Web-сайте Google Books
Библиотека пользователя на Web-сайте Google Books

Содержимое библиотеки зарегистрированного пользователя можно получить также в качестве канала Atom, пригодного для анализа в PHP-приложении. Как и перечень томов, описанный в листинге 1, этот канал содержит набор элементов <entry>, каждый из которых представляет книгу из библиотеки пользователя. Этот канал можно считать в набор PHP-объектов посредством метода объекта Zend_Gdata_Books getUserLibraryFeed(), а затем использовать для создания HTML-представления библиотеки. Это иллюстрирует листинг 6.

Листинг 6. Получение содержимого из библиотеки пользователя
<?php
// Загрузка библиотек Zend Gdata
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// Задание верительных данных для аутентификации ClientLogin
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // Регистрация 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $client->setHeaders('X-Forwarded-For', $_SERVER['REMOTE_ADDR']);
  $books = new Zend_Gdata_Books($client);

  // Получение аутентифицированного канала библиотеки пользователя
  $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;

      // Получение названия
      if (is_array($entry->getTitles())) {
        foreach ($entry->getTitles() as $title) {
          $book->titles[] = $title->getText(); 
        }
      }

      // Получение авторов
      if (is_array($entry->getCreators())) {
        foreach ($entry->getCreators() as $creator) {
          $book->authors[] = $creator->getText(); 
        }
      }

      // Получение издателей
      if (is_array($entry->getPublishers())) {
        foreach ($entry->getPublishers() as $publisher) {
          $book->publishers[] = $publisher->getText(); 
        }
      }

      // Получение даты публикации
      if (is_array($entry->getDates())) {
        $arr = $entry->getDates();
        $book->pubdate = (is_object($arr[0])) ? 
         $arr[0]->getText() : 'Unspecified'; 
      }

      // Получение номеров ISBN
      if (is_array($entry->getIdentifiers())) {
        foreach ($entry->getIdentifiers() as $id) {
          if (preg_match('/ISBN/', $id->getText())) {
            $book->isbn[] = $id->getText(); 
          }  
        }
      }

      // Получение первого предмета
      if (is_array($entry->getSubjects())) {
        $arr = $entry->getSubjects();
        $book->subject = is_object($arr[0]) ? 
         $arr[0]->getText() : 'Unspecified'; 
      }

      // Получение первого описания
      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 Book Search, инициализирует объект Zend_Gdata_Books и использует метод getUserLibraryFeed() для получения канала, содержащего список книг библиотеки пользователя. Этот канал представлен в виде массива PHP-объектов, и теперь легко перебрать массив, обработать каждую запись и отобразить результаты с соответствующей разметкой HTML.

Пример результата приведен на рисунке 8.

Рисунок 8. Результат запроса API Google Books к каналу библиотеки пользователя
Результат запроса API Google Books к каналу библиотеки пользователя's library feed shows three books with cover thumbnail and details

Добавление книг в библиотеку пользователя

Все это касается извлечения содержимого библиотеки пользователя... а как насчет добавления к ней новых наименований? С помощью API данных Google Book можно выложить в канал библиотеки пользователя XML-элемент <entry>, содержащий уникальный идентификатор тома. В листинге 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
// Загрузка библиотек Zend Gdata
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// Задание верительных данных для аутентификации ClientLogin
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // Регистрация 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $books = new Zend_Gdata_Books($client);

  // Добавление книги в библиотеку пользователя по идентификатору тома
  $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
  );

  // Отображение сообщения об успехе
  echo "Volume added successfully with ID: $id";  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

Добавление отзывов и меток для книг

Кроме добавления книг в свою библиотеку, API Google Book Search позволяет добавлять отзывы и ярлыки для отдельных книг. Отзывы и ярлыки хранятся в так называемых "аннотациях", и если оглянуться на листинг 1, можно увидеть, что каждая запись включает в себя URL аннотации. Чтобы добавить отзыв или ярлык для книги, достаточно создать XML-элемент <entry> для этой книги, приложить к ней отзывы и/или ярлыки и выложить все это по 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
// Загрузка библиотек Zend Gdata
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// Задание верительных данных для аутентификации ClientLogin
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // Регистрация 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $books = new Zend_Gdata_Books($client);

  // Добавление обзора к книге 
  $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()
  );  

  // Отображение сообщения об успехе
  echo "Review successfully added with ID: $id";  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

В листинге 10 используется метод getVolumeEntry() для получения текущей записи о книге с применением ее идентификатора тома и объекта Zend_Gdata_Books_Extension_Review, содержащего текст отзыва, с последующим его добавлением к записи с помощью метода setReview(). Метод insertVolume() заботится о создании запроса POST и редактировании записи на серверах Google.

В том же духе Google Book Search позволяет добавлять к каждой книге метку, или "ярлык" (label), с характерными ключевыми словами. Это полезная для сообщества функция, которая делает результаты поиска более эффективными и релевантными. В листинге 11 приведен пример того, как программно добавить такие ярлыки в запись книги.

Листинг 11. Снабжение книги ярлыком
<?php
// Загрузка библиотек Zend Gdata
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_Books');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');

// Указание верительных данных для аутентификации ClientLogin
$user = "xxx@gmail.com";
$pass = "secret";

try {
  // Регистрация 
  $client = Zend_Gdata_ClientLogin::getHttpClient(
    $user, $pass, 'print');
  $books = new Zend_Gdata_Books($client);

  // Добавление меток в книгу
  $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()
  );  

  // Отображение сообщения об успехе
  echo "Labels successfully added for ID: $id";  
} catch (Exception $e) {
  die('ERROR:' . $e->getMessage());  
}
?>

В листинге 11 каждый ярлык представляет собой экземпляр Zend_Gdata_App_Extension_Category, и затем эти экземпляры добавляются к записи книги с помощью метода setCategory(). После этого вызывается метод insertVolume(), который добавляет ярлыки к записи книги в базе данных Google Book Search.

Отзывы и ярлыки, добавленные в Google Book Search, не закрыты и видны всем пользователям Интернета либо на Web-сайте Google Books, либо через общедоступный канал. Например, все отзывы и ярлыки, созданные определенным пользователем, можно увидеть, просто обратившись к каналу аннотации этого пользователя по URL http://books.google.com/books/feeds/users/USER_ID/volumes. Обратите внимание, что в этом URL должен быть указан уникальный идентификатор пользователя USER_ID в службе Google Book Search, а не имя его учетной записи Google. Идентификационный номер пользователя Google Book Search можно найти по URL "My Library".


Заключение

API данных Google Book Search, хотя он все еще находится в стадии разработки, предлагает огромные возможности, позволяя разработчикам интегрировать результаты поиска книг в Web-приложения. Примеры, приведенные в этой статье, познакомили вас с каналами томов Google Book Search, показали, как искать книги по ключевым словам, автору и названию, а также проиллюстрировали, как из канала результатов поиска извлечь метаданные книги, в том числе информацию об издателе и авторах, эскизы обложки и номера ISBN. Вы прошли также ускоренный курс по изучению функций Google Book Search, предназначенных для сообщества, иллюстрирующий, как программно добавлять в записи книг отзывы и ярлыки.

Как доказывают эти примеры, REST-API Google Book Search предоставляет разработчикам новых Web-приложений огромную гибкость и свободу. Будет очень полезно, если вы попытаетесь объединить данные поиска книг с данными из других Web-сервисов или просто создать специализированный интерфейс поиска для авторов, издателей или покупателей. Поиграйте с ним какое-то время и составьте собственное мнение!

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Open source
ArticleID=627195
ArticleTitle=Интеграция службы поиска книг Google в PHP-приложение
publish-date=02162011