Flickr是学习XML Web服务的一个绝佳背景。Flickr提供了清晰的文档,具有指导性的API Explorer,允许我们在浏览器中尝试其API,以及许多混编和混搭方面的先进技术手段的研究。有许多的第三方应用都在使用Flickr API。
如前面几章(特别是第2章)讨论过的,应用编程接口(API)是实现对Web站点编程及访问其数据和服务的最佳途径,但并不是每个站点都有API。我们已经研究过许多不需要太多编程的工作,在很多情况下甚至不需要借助于API。但现在我们要来介绍API。请不要忘记那些从最终用户功能所获得的知识,在应用API的过程中你会用到这些知识。
本章最后,你会发现Flickr API也是可扩展的,通过使用它的不同选项我们能够做许多事情。不过,该API的核心其实很简单。我将给出一个(也许算得上是)最简单实用的Flickr API的例子来开始本章。通过深入地分析该例,我将从概念上介绍如何使用API中的搜索方法,以及如何理解所得到的结果。在详细说明如何构造这样一个具体的请求后,再简要介绍一些推广该例的不同途径。
在概述与该API相关的策略和服务条款后,我将进一步介绍如何理解Flickr文档,以及如何利用Flickr API Explorer这一优秀的工具来研究Flickr API。我会详细介绍调用一个基本的Flickr API方法的机制,并利用这一机会,介绍两个基本的技术:HTTP请求处理和XML解析。随后,解释如何利用这两项技术,基于照片搜索API创建一个简单的HTML界面。
有了实际使用某个方法的经验,接下来你将看到Flickr中其他的一些API方法。我会演示如何使用Flickr API中的反射(reflection)方法,并通过它来进一步介绍API本身。然后介绍一些选择不同API请求与响应格式的途径,为下一章进一步介绍REST和SOAP协议做好准备。
有了这些知识,我们应该已经可以完成几乎所有的事情了,不过这一切的前提是我们拥有合适的权限。访问授权机制是API中最复杂难懂的部分之一。如果无法理解授权每一步操作背后的动机,Flickr的授权机制可能会把你弄得很糊涂。就此,将逐一介绍Flickr授权过程中的每一步操作,并以此为基础解释Flickr授权模式的基本运作机制;同时,将展示授权过程的每个部分是如何组合在一起实现最终的整体目标的。故事有些错综复杂,但理解它们会对你掌握其他类似环境(设计约束)下的授权模式带来帮助。此后,将介绍一些具体实现以上过程的PHP代码。
在实际使用Flickr API构造混搭时,或许你并不想直接使用该API本身,而是希望利用一些API工具包或第三方提供的基于特定语言的软件包。在此,简要介绍3种面向Flickr的PHP API工具包。最后,以对Flickr API相对其UI在功能上的局限性的讨论结束本章。
6.1 Flickr API简介
在进入复杂的API应用之前,先来看一个简单的例子。简单的例子更容易帮我们避开API中繁琐复杂的细节,看到其内部简洁的核心思想。API是为程序设计人员设计的,可以用它向API本身发送请求并接收响应,其中所涉及的所有信息都能够被你的程序非常方便地解析。在较早的章节,特别是第2章中,你已经了解了可以使用Flickr的URL语言来访问Flickr中的资源。然而,为了让计算机程序能够使用这些信息,我们不得不使用屏幕抓取。屏幕抓取本身是一个脆弱而笨重的过程。相比之下,Flickr API为生成请求和获取响应建立了定义明确、稳定而简便的框架,使得计算机程序能够更加方便和可靠地使用相关的功能。
在继续工作之前,请先注册一个Flickr API键(Flickr API key),为实践下面的例子做好准备(参见下面阴影部分中的内容)。
获取Flickr API键
为了使用Flickr API,你需要一个Flickr API键。一个键就是一个数字和字母构成的字符串,它把你标识为一个API请求的来源。也即,当创建了一个API调用时,通常需要将你的键(或其他一些派生自该键的参数)传递过去。可以通过在Flickr中注册应用来获得一个键:
http://www.flickr.com/services/api/keys/apply/
为了实践本章和后续章节中的示例和练习,需要获取一个属于自己的API键。可以在如下地址查看你当前所拥有的键:
http://www.flickr.com/services/api/keys/
下一章,你将看到键其实是许多应用API都采用的一项公共机制。通过键,API提供程序能够了解到关于API使用者标识的某些信息(通常情况下,如果没有别的,至少应该包含API键所有者的e-mail地址),同时对用户访问API的方式进行监控(例如调用API或产生特定请求的频度和总量)。通过这样的跟踪监测,API提供程序能够更好地推行其API使用条款的实施--从利用e-mail联系用户,让其关闭其某个键对应的访问……到极端情况下,对某个用户的行为提起控诉。
有了你自己的键,让我们来创建一个可能是最简单的Flickr API调用。在浏览器中输入如下URL:
http://api.flickr.com/services/rest/?method=flickr.test.echo&api_key={api-key}
其中api-key是你的Flickr API键。该请求有两个参数:method和api_key,前者指明了所要访问的API的部分,后者则用于标识产生该API请求的对象(用户或用户组)。对于该请求,Flickr的响应如下:
请注意该响应的实体部分是一个包含了你的键的XML文档。
我们再来考虑一个稍微复杂些的例子,它将返回一些更有趣的东西。我们将向Flickr请求与给定标签对应的所有照片。第2章中你已经了解了如何使用Flickr UI获得对应于某个标签的所有照片,具体的URL为:
http://www.flickr.com/photos/tags/{tag}/
例如:
http://www.flickr.com/photos/tags/puppy/
相应的使用Flickr API获取某个标签对应的所有近期上传的公开照片的方式形如:
http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key={api_key}&tags={tag}&per_page={per_page}
在其中替换入你的API键,将tag设置为puppy,将per_page设置为3,具体的调用为:
http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key={api_key}&tags=puppy&per_page=3
它将得到类似如下的响应:
这个Flickr API调用中都发生了什么?在请求部分,你所要求的是最近上传的3张带有标签puppy的公开照片,所使用的方法是flickr.photos.search。在响应主体中,获得了一个XML文档。本章稍后将介绍如何使用类似PHP的语言解析XML文档。现在,请留意从该XML响应中获得的信息:
在rsp的根元素中,可以看到一个photos元素,其中包含了3个子photo元素。
photos元素的属性包含一系列与所请求的照片相关的信息:total是使用了标签puppy的公开照片的总数(288877);perpage是在该响应中实际返回的photo元素数量(3个),page为该响应对应的页码(1);最后,给定perpage的值--每页所包含的photo数,pages为总的页数(96293) 。
注解 正如Flickr的人机界面那样,使用API所得到的返回结果也是一系列的页面(试想一下API一次性地把所有puppy相关的照片数据都发给你!)。perpage的默认值是100,最大值为500。在本例中我选择其值为3,目的是使你能够更方便地分析整个响应。
每个photo元素都有一些相关的属性,能使你对照片的主题(或标题)有所了解。可以将这些属性(id、owner、secret、server和farm)映射为照片的不同URL,也可以从中了解该照片对不同类别用户(ispublic、isfriend和isfamily)的可见性。
我们来考虑关于这一请求/响应模式的两个相互关联的问题:
以上XML响应是何含义?
你能对XML响应做些什么?