`
piperzero
  • 浏览: 3475254 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

[转]YQL - 将 Web 作为数据库来使用的查询语言

阅读更多

作者:成 富, 软件工程师, IBM
来源:http://www.ibm.com/developerworks/cn/web/1011_chengfu_yql/

目前在 Web 上面已经有很多结构化数据可以供开发人员来使用。但是使用这些数据,要求对数据的请求和响应格式有一定的了解。不同服务提供者所采用的数据格式是不同的。开发人员需要查阅 Web 服务的文档和相关资料,才知道如何使用这些服务。YQL 是雅虎提供的一种类似 SQL 的查询语言,通过它可以把数据服务作为数据库表来查询,并获得结果。YQL 为开发人员提供了访问异构 Web 服务的统一视图,大大减少了开发人员的学习时间。下面具体介绍 YQL。

YQL 介绍

YQL 是雅虎推出的一种类似 SQL 的查询语言。它设计的出发点是把整个 Web 当成一个巨大的数据库,各种 Web 服务、HTML 页面、Atom/RSS 订阅源、XML 文档等都是其中的一张表。而 YQL 则作为一种通用的查询语言,可以对这些表进行查询、插入、更新和删除操作。YQL 使得开发人员可以使用一种统一的方式来访问 Web 上各种异构的数据源,大大简化了开发人员的工作。YQL 的语法与 SQL 非常类似,使得开发人员学习起来非常容易。YQL 服务的架构如图 1所示。


图 1. YQL 服务的架构
YQL 服务的架构

图 1中可以看到,YQL 服务的输入是使用者提供的 YQL 语句。YQL 服务解析 YQL 语句,然后调用后台真实的 Web 服务并获取结果。后台 Web 服务的结果以 XML 或是 JSON 的格式返回给 YQL 服务的使用者。学习 YQL 的最好做法是尝试使用它,下面介绍 YQL 控制台。

YQL 控制台

YQL 控制台是雅虎提供的一个实用工具。通过 YQL 控制台,开发人员可以直接运行 YQL 语句,并即时查看运行结果。该工具非常适合学习和调试 YQL 语句。YQL 控制台的界面如图 2所示。


图 2. YQL 控制台
YQL 控制台

受限于图片大小,图 2中并没有给出 YQL 控制台的全部内容。YQL 控制台分成两个部分:左边是 YQL 语句的输入与执行结果的显示,右边则是最近使用的 YQL 语句、示例 YQL 语句和表的列表。只需要在左上角输入 YQL 语句,选择结果的返回格式,然后点击TEST按钮就可以在左下角看到 YQL 语句的执行结果。查看结果的时候可以选择格式化好的“原始数据(FORMATTED VIEW)视图”,也可以选择“树形视图(TREE VIEW)”。如果需要直接访问 YQL 服务,可以使用 YQL 控制台上给出的查询 URL(The REST query)。在介绍完 YQL 控制台之后,下面说明使用 YQL 服务时的请求格式。

请求格式

YQL 服务提供 REST 接口,只需要用 HTTP 的 GET、PUT 和 DELETE 请求就可以完成数据的获取、添加、更新和删除操作。YQL 服务有两个不同的访问 URL:一个是http://query.yahooapis.com/v1/public/yql,这个 URL 不需要验证,只能访问公开的数据;另外一个是http://query.yahooapis.com/v1/yql,这个 URL 需要认证,可以访问公开和私有的数据。从对两个 URL 的日访问次数限制上来说,第二个 URL 的访问次数上限较高。如果要大量使用 YQL 服务的话,优先考虑使用第二个 URL。

使用 YQL 服务的时候需要提供一些参数,如表 1所示。


表 1. YQL 服务的请求参数
参数 说明
q 表示要执行的 YQL 语句。该参数是必须的。
format 表示 YQL 服务返回结果的格式。可选值有 xml 和 json,默认值是 xml。
callback 在使用 JSON 作为返回结果的格式时,该参数表示回调的 JavaScript 方法的名称。
diagnostics 表示是否在结果中包含调试诊断信息。默认值是 true。
debug 表示是否启用网络级别的日志。如果启用的话,YQL 语句中的网络调用都会被记录下来,可以在进行错误诊断的时候查看。

在介绍完 YQL 服务的请求格式之后,下面介绍返回结果的格式。

返回结果的格式

在上一节中提到 YQL 服务支持两种形式的返回结果:XML 和 JSON。通过将 HTTP 请求中的参数format设成xmljson来指定使用这两种格式。更具体的来说,返回格式还受参数callback的值的影响。具体见表 2


表 2. YQL 服务返回结果的格式
返回结果格式 参数 format 的值 参数 callback 的值 说明
XML 文档 xml 不指定 返回结果为原始的 XML 文档。
原始 JSON 数据 json 不指定 返回结果为原始的 JSON 数据。
JSONP-X xml 指定 JavaScript 方法的名称 返回结果是封装在 JavaScript 方法调用中的 JSON 数据。JSON 数据中包含实际调用结果的 XML 字符串。
JSONP json 指定 JavaScript 方法的名称 返回结果是封装在 JavaScript 方法调用中的 JSON 数据。实际调用结果的 XML 文档会被转换成 JSON 对象。

如果调用 YQL 服务的时候指定了 JSON 作为返回结果的格式,而后台服务返回的是 XML 文档的话,YQL 会自动进行 XML 到 JSON 的格式转换。由于 JSON 格式相对于 XML 来说包含的语义信息更少(如没有名称空间的概念等),这个转换过程是会损失语义的,并且不可逆的。转换过程的细节如下所示。

  • XML 文档名称空间前缀被移除。
  • XML 元素的属性被转换成 JSON 对象中的属性。
  • 如果 XML 元素中包含属性或是子元素的话,该元素会对应一个 JSON 对象,而该元素的 CDATA 和文本节点被转换成对应的 JSON 对象中的content属性;否则的话,该元素只是对应于一个字符串,其 CDATA 和文本节点作为该字符串的值。
  • 如果转换之后,同一 XML 元素的属性和子元素在 JSON 对象中的属性名称相同的话,该属性的值是一个包含所有这些属性和子元素的值的数组。

下面通过一个具体的 YQL 查询来说明返回结果的格式。该 YQL 查询用来在 Flickr 上搜索包含“beijing”的图片,使用原始的 JSON 数据作为返回结果的格式。具体的结果如代码清单 1所示。限于篇幅,只显示一条结果记录。


清单 1. YQL 服务的 JSON 格式返回结果示例
 { 
 "query": { 
  "count": "10", 
  "created": "2009-11-07T03:17:32Z", 
  "lang": "en-US", 
  "updated": "2009-11-07T03:17:32Z", 
  "uri": "http://query.yahooapis.com/v1/yql? 
        q=select+*+from+flickr.photos.search+where+text%3D%22beijing%22", 
  "diagnostics": { 
   "publiclyCallable": "true", 
   "url": { 
    "execution-time": "190", 
    "content": "http://api.flickr.com/services/rest/? 
        method=flickr.photos.search&text=beijing&page=1&per_page=10"
   }, 
   "user-time": "192", 
   "service-time": "190", 
   "build-version": "3694"
  }, 
  "results": { 
   "photo": [ 
    { 
     "farm": "3", 
     "id": "4082139618", 
     "isfamily": "0", 
     "isfriend": "0", 
     "ispublic": "1", 
     "owner": "39468173@N06", 
     "secret": "62fd8a7dd7", 
     "server": "2445", 
     "title": "北京首都国际机场"
    } 
   ] 
  } 
 } 
 }  

下面具体分析代码清单 1中给出的 JSON 数据。JSON 对象中只包含query属性,其对应的值也是一个 JSON 对象,其中有若干属性:count表示结果中的记录数;created表示结果的创建时间;updated表示结果的更新时间;lang表示结果所用的语言;uri表示获得此结果的 URL;diagnostics包含调用后台服务的相关信息,其值也是一个 JSON 对象;results表示实际的调用结果,与具体的后台服务相关。在使用 YQL 服务中,一般只需要关心results属性的值即可。下面简要介绍如何在 Web 应用中来使用 YQL 服务。

在 Web 应用中使用 YQL 服务

由于 YQL 服务提供 REST 接口,在 Web 应用中使用起来非常方便。只需要构造 HTTP GET 请求就可以完成查询操作。YQL 服务支持 JSONP 作为结果返回格式,使得在 Ajax 应用中使用起来更加简单,不需要服务器端的代理,通过 XMLHttpRequest 就可以完成请求。

使用 YQL 服务的 URL 可以根据上面提到的请求格式来创建,也可以从 YQL 控制台中得到。在 YQL 控制台右上角的“The REST query”里面包含的就是调用 YQL 服务的 URL。接下来可以用 Dojo 提供的 JSONP 支持来访问该服务,通过dojo.io.script.get就可以完成。完整的示例代码见下载

在对 YQL 服务进行介绍之后,下面具体说明 YQL 的语法。

SELECT 语句

在 YQL 语法中,SELECT语句用来从后台 Web 服务中查询数据,并进行一定的数据转换(如 XML 文档转换成 JSON 数据)。SELECT语句的作用类似于 SQL 中的SELECT语句,也是对表格型的数据进行查询。在后台服务返回的结果中,一条记录表示数据表中的一行数据,而每条记录中的字段则作为一列数据。SELECT语句的基本语法如所示。了解 SQL 语法的开发人员,看这个格式就大概知道每个部分的含义了。具体的语法见代码清单 2


清单 2. SELECT 语句的基本语法
 SELECT 字段名 FROM 表名 WHERE 过滤条件 [| 方法 ] 

SELECT的基本语法中,“字段名”对应于后台服务返回结果中的 XML 元素或是 JSON 对象中的属性,“*”表示选择全部的字段;“表名”是后台服务的名称;“过滤条件”用来声明结果中的记录应该满足的条件;“方法”用来对结果进行附加的处理,如排序和去除重复等。

在指定“字段名”的时候,多个列名之间用逗号分隔。如语句SELECT title,owner FROM flickr.photos.search WHERE text="beijing"指定了结果中只包含titleowner两个字段。如果一个字段中包含子字段的话,可以通过field1.field2的方式来指明子字段。如语句SELECT image.imageUrl FROM social.profile WHERE guid=me指定了结果中只包含字段image中的子字段imageUrl。下面具体介绍SELECT语句支持的过滤条件。

过滤条件

YQL 支持两种形式的过滤条件:远程过滤和本地过滤。远程过滤是由 YQL 服务调用的后台服务来执行的。YQL 直接把远程过滤条件传递给后台服务来处理;本地过滤是在 YQL 服务获取了后台服务的数据之后,由 YQL 服务来执行的。

由于远程过滤是由后台服务来执行的,过滤条件只支持“=”这一种。不同的后台服务所支持的用于过滤的字段是不同的,可以通过DESC语句来查看。比如想查看 Flickr 的图片信息服务支持的过滤条件,可以使用语句DESC flickr.photos.info,该语句的运行结果如代码清单 3所示,其中只保留了所需的数据。


清单 3. YQL 中 Web 服务的描述信息
 { 
 "query": { 
  "results": { 
   "table": { 
    "name": "flickr.photos.info", 
    "security": "ANY", 
    "meta": { 
     "author": "Yahoo! Inc.", 
     "documentationURL": "http://www.flickr.com/services/api/flickr.photos.getInfo.html", 
     "sampleQuery": "select * from flickr.photos.info where photo_id='2186714153'"
    }, 
    "request": { 
     "select": { 
      "key": [ 
       { 
        "name": "secret", 
        "type": "xs:string"
       }, 
       { 
        "name": "photo_id", 
        "required": "true", 
        "type": "xs:string"
       } 
      ] 
     } 
    } 
   } 
  } 
 } 
 } 

代码清单 3中,从query.results.table.request.select.key这个对象中,可以查询到该服务所支持的所有过滤条件。此处有两个条件:secretphoto_id,其中photo_id是必须的。比如 YQL 查询SELECT * FROM flickr.photos.info WHERE photo_id='2186714153'中,过滤条件photo_id='2186714153'是由 Flickr 服务来处理的。

本地过滤条件是由 YQL 服务来执行的,可以使用的过滤条件更加丰富。过滤条件的基本格式是:“列名 过滤操作符 值”。可以使用的过滤操作符如表 3所示。


表 3. YQL 服务本地过滤可用的过滤操作符
过滤操作符 说明
= 等于
!= 不等于
> 大于
< 小于
>= 大于或等于
<= 小于或等于
IN 测试是否包含在某个集合其中。既可以是一个子SELECT语句,也可以是括号中用逗号分隔的多个值。如 YQL 语句SELECT * FROM flickr.photos.recent WHERE id IN ('3630791520', '3630791510', '3630791496')中的过滤条件表示结果中记录的列id的值必须是给出的三个值之一。
IS [NOT] NULL 测试结果中的记录中是否包含某个字段。
[NOT] LIKE 进行字符串匹配。可以使用通配符“%”来表示零到多个字符。
[NOT] MATCHES 进行字符串匹配,允许使用正则表达式。

多个过滤条件可以通过布尔运算符ANDOR组合起来。下面介绍子SELECT语句。

子 SELECT 语句

在 YQL 中,可以通过子SELECT语句把来自不同后台服务的表格型数据连接(join)再一起,在功能上类似于 SQL 中的表连接操作。连接是通过IN操作符来实现的。子SELECT语句用来选择出一个字段值的集合,外部SELECT语句使用此集合的值进行过滤。比如 YQL 语句SELECT * FROM flickr.photos.info WHERE photo_id IN (SELECT id FROM flickr.photos.recent)中,子SELECT语句用来选择 Flickr 上最新上传的图片的 ID,外部SELECT语句用来根据这些图片的 ID 获取相关信息。

通过子SELECT语句进行表间连接的时候,是可以使用多个字段的。在一条SELECT语句中只允许出现一个子SELECT语句,但是子SELECT语句可以有自己的子SELECT语句。下面介绍如何对结果进行分页。

分页

一般来说,YQL 服务的返回结果的记录总数都比较大。为了提高性能,YQL 服务提供了分页能力,可以限制每次查询返回的记录数。与过滤条件类似,分页分为远程和本地两种。远程分页由后台服务执行,用来限制 YQL 服务从后台服务获取的记录数目。在远程分页的时候,可以指定两个参数,一个是第一条记录在整个结果集中的起始位置,另外一个是本次查询的返回结果中的记录数。如执行 YQL 语句SELECT * FROM flickr.photos.search(0, 20) WHERE text="beijing"的时候,YQL 服务调用 Flickr 的图片搜索服务,并只获取前 20 条记录。默认的起始位置是 0。如果使用此默认值的话,可以在 YQL 语句中省略。如之前的 YQL 语句等价于SELECT * FROM flickr.photos.search(20) WHERE text="beijing"。每次查询所能返回的记录数的最大值,是由后台服务确定的。YQL 语句SELECT * FROM flickr.photos.search(0) WHERE text="beijing"中的(0)用来设置返回结果的记录数是最大值。

在 YQL 服务从后台服务获取了数据之后,可以进行本地分页。本地分页是通过 YQL 语句中的LIMITOFFSET来指定的,可以放在WHERE子句的后面。LIMIT用来指定返回结果中的记录数,OFFSET用来指定第一条记录在整个结果集中的起始位置。如 YQL 语句SELECT * FROM flickr.photos.search(100) WHERE text="beijing" LIMIT 10 OFFSET 10中指定了本地分页,返回整个结果集的第 11 到第 20 条记录。下面介绍 YQL 语句中可以使用的排序和其它方法。

排序和其它方法

SELECT语句中,一个可选的部分是“|”之后的方法声明。YQL 服务提供了一些内置的方法,可以在完成对数据的获取和过滤等操作之后调用。比如 YQL 语句SELECT * FROM flickr.photos.search(20) WHERE text="beijing" | sort(field="title"),在以“beijing”作为关键字搜索到 20 条记录之后,对结果集根据字段title进行排序。如果使用多个方法的话,只需要在后面添加“|”和相应的方法即可。如 YQL 语句SELECT * FROM flickr.photos.search WHERE text="beijing" | sort(field="title") | truncate(count=3),在对结果根据字段title排序之后,再通过truncate(count=3)来限制只返回前面 3 条记录。YQL 服务支持的方法见表 4


表 4. YQL 服务支持的方法
名称 参数 示例 说明
sort fielddescending(可选) sort(field="title", descending="true") 根据结果集中由field指定的字段排序。descending表示是否为降序排列,默认值是false
tail count tail(count=5) 获取后count条记录。
truncate count truncate(count=5) 获取前count条记录。
reverse reverse() 倒排结果集中的全部记录。
unique field unique(field="title") 去除字段field的值有重复的记录,只保留第一条。
sanitize field(可选) sanitize(field="title") 去除记录中字段field中不安全的 HTML 字符。如果不提供参数field,则处理所有的字段。

下面介绍 YQL 服务的一个很实用的功能:屏幕抓取。

屏幕抓取

虽然 YQL 服务访问的后台 Web 服务返回的一般是 XML 和 JSON 等结构化数据,YQL 服务也可以用来从 HTML 文档中抽取数据。只需要指定 HTML 页面的 URL 以及抽取数据所用的 XPath 语句,YQL 服务就可以完成抽取。这使得 YQL 服务非常适合完成屏幕抓取的工作。下面通过一个具体的示例来说明。

该示例用来抽取百度视频搜索上热门的搜索关键词。在百度视频搜索(http://video.baidu.com)页面的右上角有一块区域用来显示热门的搜索关键词,通过查看页面的源代码,可以得到抽取关键词对应的<a>元素的 XPath 表达式://ul[@id='top']//a。完整的 YQL 语句是SELECT * FROM html WHERE url="http://video.baidu.com/" AND xpath="//ul[@id='top']//a" AND charset="gb2312"。由于该 HTML 页面所用的编码是 GB2312,此处需要通过charset="gb2312"来显式指定,否则在结果中会出现乱码。该语句的运行结果的 JSON 格式如代码清单 4所示(只给出前 3 条记录)。


padding-right: 5px; padding-left: 5px; font-weight: bold; font-size: 0.76em; padding-bottom:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics