使用 c网址 与 Google 数据服务进行交互

警告:此页面介绍的是 Google 的旧版 API(即 Google Data API),仅适用于Google Data API 目录中列出的 API,其中许多 API 已被更新的 API 取代。如需了解特定新 API,请参阅相应新 API 的文档。如需了解如何使用较新的 API 授权请求,请参阅 Google 账号身份验证和授权

Ryan Boyd,Google Data API 团队
2007 年 9 月

简介

从本质上讲,Google Data API 使用 Atom Feed 和条目 (XML) 作为数据格式,并使用 HTTP 作为数据传输协议,从而扩展了 Atom 发布协议。我们发布了许多客户端库,以便更轻松地与 Google Data API 进行交互。不过,我们始终欢迎您使用较低级别的工具来使用我们的服务,而且在我们的指导下,您很容易就能做到这一点。

c网址 是一款命令行应用,可使用各种协议(包括 HTTP)执行请求。开发者经常使用 c网址 来测试 Google 数据服务,因为它支持与 API 进行低级别交互所需的 HTTP 功能。

c网址 仅提供执行 HTTP 通信的支持,因此,要使用该应用,您必须了解 Google Data 协议、特定于服务的协议以及所用的 XML 数据格式。本文中还介绍了一些可简化这些任务的工具。

本文中的示例基于 Picasa Web Albums Data API。不过,所有这些示例都可以轻松应用于其他 Google Data API

获取和安装 c网址

在许多 UNIX/Linux 平台的默认安装中,c网址 通常可用。尝试在您喜欢的 shell 中输入 curl,看看该工具是否已安装并位于您的 PATH 中。如果您未安装该工具,请访问 c网址 网站上的下载页面,获取官方来源或用户贡献的二进制软件包。请注意,该命令行工具使用 libcurl 库,该库可能作为单独的下载软件包提供,因此,如果您不是从源代码进行编译,请务必下载“二进制”软件包,而不是“libcurl”软件包。如果您希望使用 c网址 获取身份验证令牌或访问某些需要使用 SSL 来发送请求的 Google 数据服务,则必须使用启用 SSL 的软件包。

向 Google 数据服务进行身份验证

经过身份验证的 Google 数据请求是通过向请求添加 HTTP 标头来执行的,该标头包含 ClientLogin(桌面/移动应用)或 AuthSub(Web 应用)身份验证令牌。为了便于使用 c网址 进行测试,ClientLogin 是一种更简单的方法,下面对此进行了说明。AuthSub 身份验证标头可与 c网址 搭配使用,但获取令牌的更高级流程不在本文的讨论范围内。

使用 ClientLogin

ClientLogin 适用于已安装的(桌面/移动)应用。使用此身份验证方法时,使用 Google Data API 的应用会直接处理用户的用户名和密码。

ClientLogin 的身份验证请求将用户名、密码和服务名称作为表单 POST 变量。这些变量分别作为 EmailPasswdservice 实参传递。此请求会生成包含多个令牌的响应,其中一个令牌可用于向 Google Data 服务发出请求。请注意,如果通过 curl 传递的数据实参包含非 ASCII 字符(通常出现在 EmailPasswd 实参中),则必须进行 网址编码。您可以使用 --data-urlencode 标志要求 curl 对这些实参进行网址编码。

示例请求:

curl https://www.google.com/accounts/ClientLogin \
--data-urlencode Email=brad.gushue@example.com --data-urlencode Passwd=new+foundland \
-d accountType=GOOGLE \
-d source=Google-cURL-Example \
-d service=lh2

示例回答:

SID=DQAAAHYBADCv2pSv7nflacDNwz3zEDUGtrSvNVDcpkSfddi77b3U5sEaHmP8YLWhmA36F9rk85mL8J5dqo4apn0T1vKz0fPGI9Xtnuet6cuE2ZzYvrNIwbSC_HjTqF4zudNQnnlDuD2wqZT-g1qXI8KhGAQZV4NexHZoQPlabTsGuRZeIBxj1A
LSID=EUBBBIaBADCl-kNxvRVmcQghpt3cqSMfEooKR9flLOUZqwgP9OrZS83gse-KSdTNeXhxsET7FYenDhceP9lIPOmesH-t9qh-AWUHjjMdZEbUNeF9mWyzln6Z-FajaiG-cVFkqW0ZJ8ZbnCP30xXj6xFK6QxaAcqy_9Pej8jhEnxS9E61ftQGPg
Auth=EUBBIacAAADK-kNxvRVmcQghpt3cqSMfEooLNMflLNIQqwgP9OrZS83gs-KSdTNeXhxsET7FYePWmaD8Vsy1V4LSUGMUP48Je2TO8OcjBj6HgAtPhiZeX-gKDfagZDK44j4n-Tkb44nhOnp2_QPSnBj3Z2vYwOEDjjG3Q53aQVC2132JKOuGh

如需详细了解上述请求中使用的参数,请参阅 ClientLogin 文档。在此示例中,我们使用的是 Picasa Web Albums Data API。服务名称 (service) 是 lh2。如需了解其他 Google 数据服务的服务名称,请参阅 Google Data API 常见问题解答页面。

上述响应中 Auth 令牌的值是向 Google 数据服务进行身份验证所需的唯一值。此令牌的值会形成一个 HTTP 标头,然后用于向 Google Data 服务发出的每个请求。

curl --silent --header "Authorization: GoogleLogin auth=EUBBIacAAADK\
-kNxvRVmcQghpt3cqSMfEooLNMflLNIQqwgP9OrZS83gs-KSdTNeXhxs\
ET7FYePWmaD8Vsy1V4LSUGMUP48Je2TO8OcjBj6HgAtPhiZeX-gKDfag\
ZDK44j4n-Tkb44nhOnp2_QPSnBj3Z2vYwOEDjjG3Q53aQVC2132JKOuGh" \
"http://picasaweb.google.com/data/feed/api/user/default"

注意:上述使用反斜杠字符 ('\') 转义换行符的方法在 Windows 命令 shell 中不起作用,因此如果您在 Windows 上运行 curl,则必须在一行中输入整个命令。


检索 Feed 和条目

在 Google Data API 中,检索 Feed 和条目是通过对网址执行 HTTP GET 操作完成的,并且可以选择性地使用一组查询参数。由于我们执行的是 GET 请求,因此只需将身份验证标头和网址传递给 curl。以下示例将继续使用 Picasa Web Albums Data API,用于检索经过身份验证的用户所拥有的相册列表。请注意,在此示例中,我们将身份验证令牌缩短为 ABCDEFG,但应使用完整令牌(例如上面的 EUBBIacA...32JKOuGh)来代替。

curl --silent --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/feed/api/user/default"

这将返回一个未格式化的 XML blob:

<?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:geo='http://www.w3.org/2003/01/geo/wgs84_pos#' xmlns:gml='http://www.opengis.net/gml' xmlns:georss='http://www.georss.org/georss' xmlns:photo='http://www.pheed.com/pheed/' xmlns:media='http://search.yahoo.com/mrss/' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:gphoto='http://schemas.google.com/photos/2007'><id>http://picasaweb.google.com/data/feed/base/user/brad.gushue</id><updated>2007-09-13T21:30:21.454Z</updated>...</entry></feed>

有一些不错的工具可用于格式化此输出,使其更易于阅读,包括 tidy。使用 tidy 的最简单方法是将 curl 命令的输出通过管道传递给 tidy,如下所示:

curl --silent --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/feed/api/user/default" | tidy -xml -indent -quiet

这样一来,Feed 的可读性会大大提高,如下所示:

<?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:geo='http://www.w3.org/2003/01/geo/wgs84_pos#' 
xmlns:gml='http://www.opengis.net/gml' 
xmlns:georss='http://www.georss.org/georss' 
xmlns:photo='http://www.pheed.com/pheed/' 
xmlns:media='http://search.yahoo.com/mrss/' 
xmlns:batch='http://schemas.google.com/gdata/batch' 
xmlns:gphoto='http://schemas.google.com/photos/2007'>
  <id>http://picasaweb.google.com/data/feed/api/user/brad.gushue</id>
  <updated>2007-09-13T21:47:07.337Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind'
  term='http://schemas.google.com/photos/2007#user' />
  <title type='text'>brad.gushue</title>
  <subtitle type='text'></subtitle>
  <icon>
  http://lh6.google.com/brad.gushue/AAAAj9zigp4/AAAAAAAAAAA/RiMAlXV4MFI/s64-c/brad.gushue</icon>
  <link rel='http://schemas.google.com/g/2005#feed'
  type='application/atom+xml'
  href='http://picasaweb.google.com/data/feed/api/user/brad.gushue' />
  <link rel='alternate' type='text/html'
  href='http://picasaweb.google.com/brad.gushue' />
  <link rel='self' type='application/atom+xml'
  href='http://picasaweb.google.com/data/feed/api/user/brad.gushue?start-index=1&max-results=1000' />
  <author>
    <name>Brad</name>
    <uri>http://picasaweb.google.com/brad.gushue</uri>
  </author>
  <generator version='1.00' uri='http://picasaweb.google.com/'>
  Picasaweb</generator>
  <openSearch:totalResults>8</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>1000</openSearch:itemsPerPage>
  <gphoto:user>brad.gushue</gphoto:user>
  <gphoto:nickname>Brad</gphoto:nickname>
  <gphoto:thumbnail>
  http://lh6.google.com/brad.gushue/AAAAj9zigp4/AAAAAAAAAAA/RiMAlXV4MFI/s64-c/brad.gushue</gphoto:thumbnail>
  <entry>
    <id>
    http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593</id>
    <published>2007-05-23T04:55:52.000Z</published>
    <updated>2007-05-23T04:55:52.000Z</updated>
    <category scheme='http://schemas.google.com/g/2005#kind'
    term='http://schemas.google.com/photos/2007#album' />
    <title type='text'>Trip To Italy</title>
    <summary type='text'>This was the recent trip I took to
    Italy.</summary>
    <rights type='text'>public</rights>
    <link rel='http://schemas.google.com/g/2005#feed'
    type='application/atom+xml'
    href='http://picasaweb.google.com/data/feed/api/user/brad.gushue/albumid/9810315389720904593' />
    <link rel='alternate' type='text/html'
    href='http://picasaweb.google.com/brad.gushue/TripToItalyV2' />
    <link rel='self' type='application/atom+xml'
    href='http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593' />
    <link rel='edit' type='application/atom+xml'
    href='http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593/123456' />
    <author>
      <name>Brad</name>
      <uri>http://picasaweb.google.com/brad.gushue</uri>
    </author>
    <gphoto:id>9810315389720904593</gphoto:id>
    <media:group>
    ...
    </media:group>
  </entry>
  <entry>
  ...
  </entry>

</feed>

您可以通过提供条目的网址(而非 Feed 网址)来检索单个条目,方法与检索整个 Feed 相同。

更新条目

Google Data API 中的条目是通过以下方式更新的:向编辑网址执行 HTTP PUT,并在请求正文中包含条目 XML 的新副本。

  1. 使用 atom:link/@rel='self' 网址值检索条目
  2. 在本地更新条目以进行所需更改
  3. PUT 使用 atom:link/@rel='edit' 网址值将条目返回到服务器

1. 检索条目

您可以使用上述 Feed 代码块中以粗体显示的两个网址之一来检索相应条目。所需的网址是具有 rel='self'link 元素的 href 值。

curl --silent --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593"

2. 在本地更新条目

检索条目后,需要使用本地文本编辑器或应用更新该条目,以便对条目进行任何必要的更改。在上面的命令中,我们没有像之前的示例那样将结果通过管道传输到 tidy。结果是表示相同数据的 XML,但格式与通过管道传输到 tidy 的版本不同。为了手动修改条目,使用 tidy 通常可以更轻松地处理 XML。

注意:发布新条目时,请务必包含所有用作 atom:entry 属性的 XML 命名空间定义。如果省略这些内容,则会导致解析异常。此外,tidy 会将命名空间定义之间的空格替换为换行符。虽然这是有效的 XML,但 Google Data 服务目前不接受。如果您使用的是 tidy,请务必在 entry 元素上在这两个属性之间添加额外的空格。

3. 更新服务器上的条目

使用 edit 网址,您需要使用 c网址 PUT 服务条目的副本。需要添加一个标头来指明发送到服务器的内容类型。以下代码段假定包含更新后条目的文件已保存为 updated_entry.xml。

curl --silent --data-binary "@updated_entry.xml" --request PUT --header "Content-Type: application/atom+xml" --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593/123456"

创建条目

Google Data API 中的条目是通过向发布网址发送包含新条目的 HTTP POST 请求来创建的。atom:id 由服务器分配,因此无需包含在新条目中。创建新条目的最简单方法是采用旧条目并对其进行修改。以下示例将执行此操作。

  1. 使用 atom:link/@rel='self' 检索模板条目
  2. 在本地修改模板条目,以移除不必要的信息并进行所需的更改
  3. POST 使用 Feed 的 post 网址将条目发送回服务器。此值可在检索到的 Feed 中找到,是 rel='http://schemas.google.com/g/2005#post'link 元素的 href 值,也可在 http://code.google.com 上找到相应服务的文档。

1. 检索模板条目

可以使用 href 值为 rel='self'link 元素检索单个条目,就像在上述示例中更新条目之前检索条目一样。

curl --silent --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593" | tidy -xml -indent -quiet > template_entry.xml

使用 tidy 后的响应如下所示:

<entry xmlns='http://www.w3.org/2005/Atom' 
xmlns:exif='http://schemas.google.com/photos/exif/2007'
xmlns:geo='http://www.w3.org/2003/01/geo/wgs84_pos#'
xmlns:gml='http://www.opengis.net/gml'
xmlns:georss='http://www.georss.org/georss'
xmlns:photo='http://www.pheed.com/pheed/'
xmlns:media='http://search.yahoo.com/mrss/'
xmlns:batch='http://schemas.google.com/gdata/batch'
xmlns:gphoto='http://schemas.google.com/photos/2007'>
  <id>
  http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389741123981</id>
  <published>2007-05-23T04:55:52.000Z</published>
  <updated>2007-05-23T04:55:52.000Z</updated>
  <category scheme='http://schemas.google.com/g/2005#kind'
  term='http://schemas.google.com/photos/2007#album' />
  <title type='text'>Trip To Italy</title>
  <summary type='text'>This was the recent trip I took to
  Italy.</summary>
  <rights type='text'>public</rights>
  <link rel='http://schemas.google.com/g/2005#feed'
  type='application/atom+xml'
  href='http://picasaweb.google.com/data/feed/api/user/brad.gushue/albumid/9810315389741123981' />
  <link rel='alternate' type='text/html'
  href='http://picasaweb.google.com/brad.gushue/TripToItaly' />
  <link rel='self' type='application/atom+xml'
  href='http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389741123981' />
  <link rel='edit' type='application/atom+xml'
  href='http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389741123981/1179896152905401' />
  <author>
    <name>Brad</name>
    <uri>http://picasaweb.google.com/brad.gushue</uri>
  </author>
  <gphoto:id>9810315389741123981</gphoto:id>
  <gphoto:name>TripToItaly</gphoto:name>
  <gphoto:location></gphoto:location>
  <gphoto:access>public</gphoto:access>
  <gphoto:timestamp>1179896152000</gphoto:timestamp>
  <gphoto:numphotos>0</gphoto:numphotos>
  <gphoto:numphotosremaining>500</gphoto:numphotosremaining>
  <gphoto:bytesUsed>0</gphoto:bytesUsed>
  <gphoto:user>brad.gushue</gphoto:user>
  <gphoto:nickname>Brad</gphoto:nickname>
  <gphoto:commentingEnabled>true</gphoto:commentingEnabled>
  <gphoto:commentCount>0</gphoto:commentCount>
  <media:group>
    <media:title type='plain'>Trip To Italy</media:title>
    <media:description type='plain'>This was the recent trip I took
    to Italy.</media:description>
    <media:keywords></media:keywords>
    <media:content url='http://lh5.google.com/brad.gushue/ADFUFKqeA5E/AAAAAAAAABc/V6Sga_Z03WU/TripToItaly.jpg'
    type='image/jpeg' medium='image' />
    <media:thumbnail url='http://lh5.google.com/brad.gushue/ADFUFKqeA5E/AAAAAAAAABc/V6Sga_Z03WU/s160-c/TripToItaly.jpg'
    height='160' width='160' />
    <media:credit>Brad</media:credit>
  </media:group>

</entry>

2. 修改模板条目

我们想创建一个名为“加拿大冰壶”的相册,其中包含我们最近参加的冰壶比赛的照片。Google Data 允许您舍弃服务器提供值的 Atom 元素,因此为了创建这个简单的模板条目,我们将移除 Feed 中的 atom:idatom:publishedatom:updatedatom:author 和各种 atom:link 元素。这样会生成一个精简的模板条目。然后,需要修改该条目以表示我们正在创建的新专辑:

<entry xmlns='http://www.w3.org/2005/Atom' 
xmlns:gphoto='http://schemas.google.com/photos/2007'>
  <category scheme='http://schemas.google.com/g/2005#kind'
  term='http://schemas.google.com/photos/2007#album' />
  <title type='text'>Curling in Canada</title>
  <summary type='text'>Pictures of all my curling matches in Canada.</summary>
  <gphoto:location>Canada</gphoto:location>
  <gphoto:access>public</gphoto:access>
  <gphoto:commentingEnabled>true</gphoto:commentingEnabled>

</entry>

注意:发布新条目时,请务必包含所有用作 atom:entry 属性的 XML 命名空间定义。如果省略这些内容,则会导致解析异常。此外,tidy 会替换命名空间定义之间的空格,并将其替换为换行符。虽然这是有效的 XML,但 Google Data 服务目前不接受。如果您使用的是 tidy,请务必在 entry 元素上在这两个属性之间添加额外的空格。

3. 将新条目发布到服务器

用于向服务器发布新条目的 curl 命令与更新现有条目的命令非常相似,只是网址不同:

curl --silent --request POST --data-binary "@template_entry.xml" --header "Content-Type: application/atom+xml" --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/feed/api/user/brad.gushue" | tidy -xml -indent -quiet

如果发布成功,生成的 XML 输出将是新创建条目的副本。此条目将包含服务器在创建条目时生成的内容,包括 atom:idatom:publishedatom:updatedatom:link 元素的值。生成的 link 值可用于修改或删除相应条目,前提是在此期间未进行其他更改。

删除条目

删除条目与更新条目非常相似,只是前者使用 HTTP DELETE 方法,而不是 HTTP PUT 方法,并且不需要发送任何数据。与更新请求类似,edit 网址也用作 HTTP 请求的目标。

curl --silent --request DELETE --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/entry/api/user/brad.gushue/albumid/9810315389720904593/123456"

上传媒体对象

Picasa Web Albums Data API 和 Documents List Data API 的一项重要功能是能够上传二进制对象。c网址 可以轻松完成二进制数据和 slug 标头的上传。不过,Documents List Data API 目前要求将 XML 与二进制数据一起作为 MIME 多部分消息进行发布。本文不讨论如何创建多部分消息。

以下示例展示了如何将名为 sweeping_the_rock.png 的图片上传到标题为“Sweeping the rock”的 Picasa 线上相册:

curl --silent --request POST --data-binary "@sweeping_the_rock.png" --header "Slug: Sweeping the rock" --header "Content-Type: image/png" --header "Authorization: GoogleLogin auth=ABCDEFG" "http://picasaweb.google.com/data/feed/api/user/brad.gushue/albumid/5113621341847124417" | tidy -xml -indent -quiet

其他命令行工具

有些开发者更喜欢使用其他命令行工具进行学习或调试。

热门工具包括:

  • telnet、openssl 用于与 Web 服务器建立原始套接字连接(分别为纯文本连接和基于 SSL 的连接),并可用于与 Google Data 服务互动。请注意,并非所有 Google 数据服务都支持 SSL。以下是建立连接的方法:
    • telnet picasaweb.google.com 80 (Picasa Web Albums Data API)
    • openssl s_client -connect www.google.com:443(Google 日历数据 API 和 www.google.com 上的其他服务)
    建立连接后,必须发送原始 HTTP 请求。此请求包含 HTTP 动词、相对路径、版本、所有标头和请求正文。示例如下:
    POST /data/feed/api/user/brad.gushue HTTP/1.1
    Host: picasaweb.google.com
    Authorization: GoogleLogin auth=ABCDEFG
    Content-Length: 493
    
    <entry xmlns='http://www.w3.org/2005/Atom' 
    xmlns:gphoto='http://schemas.google.com/photos/2007'>
      <category scheme='http://schemas.google.com/g/2005#kind'
      term='http://schemas.google.com/photos/2007#album' />
      <title type='text'>Curling in Canada</title>
      <summary type='text'>Pictures of all my curling matches in Canada.</summary>
      <gphoto:location>Canada</gphoto:location>
      <gphoto:access>public</gphoto:access>
      <gphoto:commentingEnabled>true</gphoto:commentingEnabled>
    
    </entry>
    
    发送原始 HTTP 数据时,请注意 POSTPUT 操作需要计算 Content-Length 标头的值。您可以使用 UNIX 工具 wc 计算此值。将 HTTP 正文的所有内容放入一个文本文件(例如 template_entry.xml,即上文使用的示例),然后运行 wc -c template_entry.xml。如果您不小心为 Content-Length 标头使用了错误的值,则通常很难进行调试。
  • wget 通常用于将数据从 Web 服务器下载到本地文件。不过,wget 提供了许多选项,使其能够执行与 Google 数据服务互动所需的所有不同类型的请求。以下示例展示了如何使用 wget 向 Picasa 网络相册 POST 新的相册条目:
    wget --post-file template_entry.xml --header "Authorization: GoogleLogin auth=ABCDEFG" --header "Content-Type: application/atom+xml" "http://picasaweb.google.com/data/feed/api/user/brad.gushue"
    
  • xsltproc 是一种将 XSL 转换 (XSLT) 应用于 XML 文档的工具。您可以使用它轻松地从 Google Data API 返回的 XML 条目或 Feed 中提取所需的数据位,或者生成新的或更新的条目。

总结

如您所见,c网址 和其他几种命令行工具可用于通过原始 XML 和 HTTP 轻松与 Google 数据服务进行交互。如果您在使用这些工具时遇到任何问题,或者想将这些工具与您喜爱的 Google Data API 搭配使用,请加入我们的 API 专用论坛