雅虎yql php
2010年11月30日- 在“ 简介和结论”部分中添加了指向第1部分的链接。 在“ 相关主题 ”中的“学习”下,为第2部分添加了资源项。
如今,几乎每个流行的网站都有一个开发人员API,允许Web应用程序程序员使用诸如REST和SOAP之类的标准框架来访问和操纵数据。 例如,Google提供了Google Data API,用于访问Google服务,例如Google Buzz,Google Docs和Google Calendar。 Twitter有一个REST API,允许用户搜索和发布推文; Facebook提供了Graph API来管理用户配置文件和连接。
这些API无疑使您的生活更加令人兴奋,并为各种创新的新应用程序打开了大门,但仍然存在一些挑战。 例如,关键的实现挑战是不同站点的API之间缺乏统一性。 有些站点使用REST,而另一些站点则使用SOAP。 一些使用Atom编码响应数据,但是其他一些使用RSS,还有一些使用纯XML或JSON。 因此,每次决定将新的Web服务集成到应用程序中时,首先必须进行大量的阅读,然后进行大量的测试以完全掌握服务API的机制,然后再开始进行集成。
为了解决这个问题,Yahoo!的开发人员 决定发明Yahoo! 查询语言,以缩写词YQL闻名。 YQL为多个Web服务API提供了一个类似SQL的统一接口,从而大大简化了将第三方数据集成到Web应用程序中的任务。 在这个由两部分组成的文章中,我向您介绍YQL,说明如何与我最喜欢的语言PHP结合使用它来构建复杂的Web应用程序。
了解YQL
如果您熟悉SQL,YQL会立即对您熟悉。 很简单,YQL将单个Web服务视为数据表,使开发人员可以制定类似于SQL的查询以从中提取信息。 YQL服务负责解析查询字符串,在远程服务上执行查询字符串,并以标准XML或JSON格式返回结果。 查询字符串本身使用REST作为GET请求传递给YQL服务。
为了更好地理解这种方法,请考虑一个简单的示例。 假设您想在Twitter上搜索所有包含“首席负责人”一词的帖子。 在非YQL的世界中,通常可以通过制定如下这样的请求,通过Twitter Search API来执行此操作:
http://search.twitter.com/search.atom?q=master%20chief&lang=en
作为回报,Twitter Search API发送回Atom结果提要,例如图1所示 。
图1.来自Twitter Search API的搜索结果的Atom提要
使用YQL,您可以通过使用YQL查询访问Twitter数据表来简化操作,如下所示:
SELECT * FROM twitter.search WHERE q='master chief'
请注意,这几乎完全类似于标准SQL查询:SELECT关键字指示这是一个数据检索操作,FROM关键字指定数据源,WHERE子句指定过滤器。 提交此查询后,YQL返回一个标准XML或JSON文档,其中包含来自Twitter的查询结果, 如图2所示 。
图2. Twitter数据表上的YQL查询结果
现在,跳过几天,并假设您决定向Web应用程序中添加更多数据。 具体来说,假设您想使用Twitter搜索结果附带的地理编码信息来显示每个帖子所来自的地理区域的地图。 还要假设您希望在Twitter搜索结果中随附有关搜索字词“首席负责人”的新闻标题列表。
在非YQL的世界中,您需要花一些时间阅读Yahoo!的API文档。 地图和Google新闻,然后才能完成此任务。 使用YQL,就像添加几个查询一样简单:
SELECT * FROM google.news WHERE q="master chief"
SELECT * FROM maps.map WHERE latitude="XX" AND longitude="YY"
图3.在Google News数据表上进行YQL查询的结果
图4. Yahoo Maps数据表上的YQL查询结果
图3和4中的查询结果清楚地表明,YQL的最大好处在于为第三方Web服务提供了统一的界面。 通过允许您使用通常理解SQL语法查询第三方服务,YQL节省了您的时间和精力,并使将来自不同来源的数据集成到Web应用程序中变得更加容易。 选择XML或JSON作为输出格式的功能也很有用,可以为您提供一定程度的灵活性,并允许您使用服务器端编程(例如PHP Perl)或客户端工具(jQuery或mooTools,用于实例)以访问和操作结果数据。
使用YQL控制台
开始使用YQL的最简单方法是通过YQL控制台,这是一个交互式的在线工具,可让您即时制定和测试YQL查询。 YQL控制台托管在Yahoo!上。 开发人员网络,并附带诊断工具,示例查询和可用表列表。
要查看其工作原理,请浏览到YQL控制台并在其中输入以下查询,以获取当前流行的音乐专辑列表:
SELECT * FROM music.release.popular
提交表单时,查询字符串将作为URL编码查询字符串提交到YQL服务。 然后,YQL服务查找表定义,执行查询并返回结果。 图5说明了YQL控制台中的输出。
图5. YQL交互式控制台中的查询输出
在PHP中使用YQL
如图5所示,YQL可以使用XML或JSON返回数据。 在构建PHP Web应用程序时,XML通常更方便,因为PHP带有内置的XML处理扩展(SimpleXML,DOM或XMLReader),可用于快速解析结果文档。 考虑到这一点, 清单1尝试使用PHP和SimpleXML执行相同的查询:
清单1.使用SimpleXML处理YQL结果
<?php
// execute query
// get list of 15 most popular music releases
// retrieve result as SimpleXML object
$xml = simplexml_load_file('
http://query.yahooapis.com/v1/public/yql?q=
SELECT * FROM music.release.popular
');
// iterate over query result set
echo '<h2>Popular Music</h2>';
$results = $xml->results;
foreach ($results->Release as $r) {
echo '<p>';
echo '<a href="' . $r['url'] . '">' . $r['title'] .
'</a> (' . $r['releaseYear'] . ') - ';
echo '<a href="' . $r->Artist['url'] . '">' . $r->Artist['name'] .
'</a> <br/>';
echo 'Current chart position: ' . $r->ItemInfo->ChartPosition['this'] .
' / Last chart position: ' . $r->ItemInfo->ChartPosition['last'];
echo '</p>';
}
?>
清单1首先是对YQL Web服务制定查询,然后向其传递与上一个示例中相同的URL编码查询字符串。 该请求是通过simplexml_load_file()
函数发出的,从而确保了结果XML文档被自动解析并转换为SimpleXML对象。 然后,脚本的其余部分遍历XML文档的<results>
节点,为每个专辑打印标题,链接,艺术家和当前图表位置。
图6说明了结果。
图6.通过YQL检索的流行音乐发行列表
如果使用Zend Framework,则可以使用Zend_Rest_Client组件访问YQL Web服务。 清单2展示了产生与清单1相同的输出的清单 。
清单2.使用Zend框架处理YQL结果
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');
// execute YQL query
// get list of most popular music releases
try {
$client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
$client->q('SELECT * FROM music.release.popular');
$result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// iterate over query result set
echo '<h2>Popular Music</h2>';
foreach ($result->Release as $r) {
echo '<p>';
echo '<a href="' . $r['url'] . '">' . $r['title'] .
'</a> (' . $r['releaseYear'] . ') - ';
echo '<a href="' . $r->Artist['url'] . '">' . $r->Artist['name'] .
'</a> <br/>';
echo 'Current chart position: ' . $r->ItemInfo->ChartPosition['this'] .
' / Last chart position: ' . $r->ItemInfo->ChartPosition['last'];
echo '</p>';
}
?>
Zend Framework的Zend_Rest_Client组件是专门为尝试将PHP应用程序与基于REST的Web服务集成的开发人员设计的。 使用此客户端,您可以对REST服务端点执行GET,POST,PUT和DELETE响应。 REST响应作为Zend_Rest_Client_Response对象的实例返回,从而可以轻松访问各个响应属性。
清单2首先加载Zend类库,然后初始化Zend_Rest_Client类的实例。 该客户端用于为YQL Web服务端点初始化未经身份验证的GET请求,如清单1所示 。 然后,解析返回的XML文件并将其转换为Zend_Rest_Client_Response对象,然后可以使用标准的foreach()循环对其进行处理。 请注意,使用Zend_Rest_Client对象时,无需对YQL查询进行URL编码,因为该组件在内部负责该步骤。
过滤和排序查询结果
与常规SELECT查询一样,YQL允许您使用WHERE子句过滤查询结果,指定必填字段并按一个或多个字段对结果进行排序。 为了说明这一点,请考虑对Flickr API进行以下查询,以获取与搜索词“ england”匹配的地点的列表:
SELECT * FROM flickr.places WHERE query="england"
图7说明了对该查询的YQL响应。
图7.通过YQL从Flickr中检索到的“英国”的搜索结果列表
清单3在实践中说明了此查询。
清单3.使用WHERE子句过滤YQL结果
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');
// execute YQL query
// get list of Flickr places matching search term
try {
$client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
$client->q('SELECT * FROM flickr.places WHERE query="england"');
$result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// iterate over query result set
echo '<h2>Search Results</h2>';
echo '<table border=1>';
echo '<tr><th>Name</th><th>Latitude</th><th>
Longitude</th></tr>';
foreach ($result->place as $p) {
echo '<tr>';
echo '<td>' . $p . '</td>';
echo '<td>' . $p['latitude'] . '</td>';
echo '<td>' . $p['longitude'] . '</td>';
echo '</tr>';
}
echo '</table>';
?>
图8.通过YQL从Flickr中检索的“英国”搜索结果的格式化列表
您可以使用AND和OR运算符添加其他过滤条件。 考虑上一个查询的此修订版,该修订版进一步按时timezone
过滤结果:
SELECT * FROM flickr.places WHERE query="england" AND timezone LIKE "%europe%"
您只能将查询的输出限制为特定的字段。 当您只需要Web服务返回的一小部分数据时,此方法很有用,并且还可以减小响应数据包的大小。 这是对先前示例的修订,该示例仅检索每个记录的纬度,经度和名称:
SELECT latitude, longitude, content FROM flickr.places WHERE query="england"
YQL还支持各种实用程序功能,这些功能可用于对结果集中的重复项进行计数,计数和消除重复项。 这些函数通常放在YQL查询字符串之后,并用竖线(|)分隔。 考虑以下查询,该查询按纬度对结果进行排序:
SELECT latitude, longitude, content FROM flickr.places
WHERE query="england" | sort (field="latitude")
您还可以应用唯一过滤器从结果中去除重复项,并指定应检查的字段:
SELECT * FROM flickr.places
WHERE query="england" | unique (field="timezone")
清单4将所有这些放在一起以构建一个交互式查询工具,该工具要求用户输入位置名称并返回可排序的结果列表。
清单4.搜索地名
<html>
<head></head>
<body>
<form method="post" action="<?php echo htmlentities
($_SERVER['PHP_SELF']); ?>">
Search term:
<input type="text" name="q" />
Sort results by:
<select name="s">
<option value="timezone">Time zone</option>
<option value="latitude">Latitude</option>
<option value="longitude">Longitude</option>
</select>
<input type="submit" name="submit" value="Search" />
</form>
<?php
// check if form is submitted
// perform necessary validation (omitted for brevity)
if (isset($_POST['submit'])) {
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');
// execute YQL query
// get list of Flickr places matching search term
// sort by requested field
try {
$client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
$client->q(
'SELECT latitude, longitude, timezone, content FROM flickr.places
WHERE query="' . $_POST['q'] .'" | sort(field="' . $_POST['s'] . '")');
$result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// iterate over query result set
echo '<h2>Search Results</h2>';
echo '<table border=1>';
echo '<tr><th>Name</th><th>Timezone</th>
<th>Latitude</th><th>Longitude</th></tr>';
foreach ($result->place as $p) {
echo '<tr>';
echo '<td>' . $p . '</td>';
echo '<td>' . $p['timezone'] . '</td>';
echo '<td>' . $p['latitude'] . '</td>';
echo '<td>' . $p['longitude'] . '</td>';
echo '</tr>';
}
echo '</table>';
}
?>
</body>
</html>
图9.地名的交互式搜索和排序过滤器
有关YQL功能的完整列表,请查看《 YQL指南》( 有关链接,请参阅参考资料)。
一个示例应用程序:按位置的天气预报
现在,让我们利用到目前为止所学到的所有知识,并使用PHP构建一个简单的YQL支持的应用程序。 清单5要求用户在表格中输入他或她的位置; 然后连接到Yahoo! 通过weather.bylocation表提供天气服务,并查询该位置的本地天气预报。 看一下清单5中的代码。
清单5.按位置检索天气预报
<html>
<head></head>
<body>
<form method="post" action="<?php echo htmlentities
($_SERVER['PHP_SELF']); ?>">
Enter city name:
<input type="text" name="city" />
<input type="submit" name="submit" value="Get forecast" />
</form>
<?php
// check if form is submitted
// perform necessary validation (omitted for brevity)
if (isset($_POST['submit'])) {
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');
// execute YQL query
// get Yahoo! Weather forecast for selected zip code
try {
$client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
$client->env('store://datatables.org/alltableswithkeys');
$client->q('SELECT * FROM weather.bylocation
WHERE location="' . $_POST['city'] . '"');
$result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// process and print query results
$data = $result->results->weather->rss->channel->item;
echo '<h2>' . $data->title . '</h2>';
echo $data->pubDate . '<br/>';
echo $data->description;
}
?>
</body>
</html>
提交带有城市名称的Web表单后, 清单5使用Zend_Rest_Client组件将YQL查询发送到气象服务。 该查询使用WHERE子句来过滤weather.bylocation表的内容,并检索指定邮政编码的天气预报。 查询结果将格式化并显示为HTML页面。 图10说明了结果。
图10.通过YQL检索的各城市天气预报
还要注意, 清单5向查询字符串env
添加了一个新变量。 该变量是必需的,因为weather.bylocation数据表是所谓的社区表 ,由社区而不是Yahoo!维护。 本身。 结果,YQL服务不会自动知道此表定义的位置。 env
变量用于指定表定义文件的位置。 在这种情况下,该位置是YQL网站,其作为所有YQL社区表(见库中的社区开放数据表相关信息中的链接)。
使用嵌套的YQL查询
传统RDBMS的最大价值在于将单个表连接在一起以创建其中包含的数据的不同视图的能力。 关于YQL的最酷的事情之一是,它使您可以使用Web服务执行相同的操作。 使用YQL查询,可以合并来自多个Web服务的数据,以呈现第三方数据的新的有用视图。
虽然此功能的可能应用仅受您的创造力的限制,但是一个简单的示例可以帮助您清楚地了解此功能的强大功能。 考虑清单6 ,它要求用户输入国家/地区名称,然后查询即将到来的Web服务以列出该国家/地区即将发生的事件。
清单6.按国家搜索事件
<html>
<head></head>
<body>
<form method="post"
action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
Search for events in:
<input type="text" name="country" />
<input type="submit" name="submit" value="Search" />
</form>
<?php
// check if form is submitted
// perform necessary validation (omitted for brevity)
if (isset($_POST['submit'])) {
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');
// execute YQL query
// get list of events in requested country
try {
$client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
$client->q(
"SELECT * FROM upcoming.events
WHERE country_id IN
(SELECT id FROM upcoming.country
WHERE name = '" . ucfirst($_POST['country']) . "')");
$result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// iterate over query result set
echo '<h2>Events in ' . ucfirst($_POST['country']) . '</h2>';
foreach ($result->event as $e) {
echo '<p>';
echo '<a href="' . $e['url'] . '">' . $e['name'] .
'</a> <br/>';
echo 'Starts: ' . date('d M Y', strtotime($e['start_date'])). '<br/>';
echo !empty($e['end_date']) ? 'Ends: ' .
date('d M Y', strtotime($e['end_date'])) . '<br/>' : '';
echo 'Location: ' . $e['venue_name'] . '<br/>';
echo 'Address: ' .
sprintf('%s, %s', $e['venue_address'], $e['venue_city']) . '<br/>';
echo $e['description'] . '<br/>';
echo '</p>';
}
}
?>
</body>
</html>
清单6使用了两个嵌套的YQL查询。 内部查询访问“ upcoming.country”数据表以检索与用户输入的国家/地区字符串相对应的数字ID。 然后,此数字ID传递到外部查询,以检索链接到该国家ID的事件列表。
图11说明了结果的示例。
图11.即将发生的事件的列表,可以按国家搜索
重要的是要注意,从技术上讲,这不是联接,而是子查询。 在撰写本文时,YQL不允许您通过公用键(联接)链接表,而仅允许您在另一个查询(子查询)中使用一个查询的结果。
一个示例应用程序:畅销书列表和价格
就像您想象的那样,使用简单的类似于SQL的语法将来自多个Web界面的数据组合在一起的能力在mashup开发人员耳中是一种音乐。 因此,让我们考虑另一个稍微复杂一点的应用程序:将《纽约时报》畅销书列表中的数据与Amazon.com数据库中的价格信息相结合,以呈现热门图书,其价格和受欢迎程度的综合视图。
构建此应用程序的第一步是获取《纽约时报》畅销书的最新列表。 YQL通过其nyt.bestsellers表提供了此信息,但是您需要有效的API密钥才能对该表运行查询。 假设您具有此密钥(请在参考资料中找到解释如何获得此链接的链接),则可以使用以下查询检索2010年7月21日当周精装小说畅销书的当前列表:
SELECT * FROM nyt.bestsellers WHERE listname='Hardcover Fiction'
AND date='2010-07-21' AND apikey='NYT-API-KEY'
图12说明了该查询的输出。
图12.通过YQL检索的《纽约时报》畅销书列表
请注意,结果中的每个记录都列出了该书的唯一ISBN号。 这是应用程序第二部分的关键信息,需要在Amazon.com上查询这本书的价格。
乍一看,从Amazon.com提取价格数据似乎是一项艰巨的任务,但实际上,这再简单不过了。 Amazon.com通过其Amazon ECS Web服务将其产品数据库公开给第三方开发人员(请参阅参考资料中的链接和有关如何获取API密钥的信息)。 YQL包括Amazon ECS的数据表,从而可以通过类似这样的查询来检索特定ISBN的定价信息:
SELECT DetailPageURL, ItemAttributes, SalesRank, MediumImage FROM amazon.ecs
WHERE AWSAccessKeyId='AWS-KEY' AND secret='AWS-SECRET-KEY'
AND ResponseGroup='Medium' AND Operation = 'ItemLookup'
AND ItemAttributes.Binding = 'Hardcover' AND ItemId = '1400065453'
图13说明了此查询的输出。
图13.通过YQL检索的Amazon.com产品数据
应当清楚,前面的两个查询可以轻松组合以产生必要的信息。 清单7具有完整的脚本。 在尝试之前,请记住用您自己的查询替换虚拟API密钥。
清单7.检索畅销书列表和价格
<html>
<head>
<style type="text/css">
.item {
float: left;
width: 400px;
padding:10px;
}
.cover {
float:left;
padding: 5px;
border: solid 1px black;
}
.data {
margin-left: 150px;
font-weight: bolder;
}
</style>
</head>
<body>
<?php
// set up Zend auto-loader
// load Zend REST client classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Rest_Client');
// execute YQL query
// get list of NYT bestsellers
// retrieve image and price from Amazon.com
try {
$client = new Zend_Rest_Client('http://query.yahooapis.com/v1/public/yql');
$client->env('store://datatables.org/alltableswithkeys');
$client->q(
"SELECT DetailPageURL, ItemAttributes, SalesRank, MediumImage FROM amazon.ecs
WHERE AWSAccessKeyId='AWS-KEY'
AND secret='AWS-SECRET-KEY'
AND ResponseGroup='Medium'
AND Operation = 'ItemLookup'
AND ItemAttributes.Binding = 'Hardcover'
AND ItemId IN
(SELECT isbns.isbn.isbn10 FROM nyt.bestsellers
WHERE apikey='NYT-KEY'
AND listname='Hardcover Fiction'
AND date='2010-07-20')
| unique(field='ItemAttributes.Title')");
$result = $client->get();
} catch (Zend_Rest_Client_Exception $e) {
echo "Client error: " . $e->getResponse();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
// iterate over query result set
echo '<h2>New York Times - Hardcover Fiction Bestsellers</h2>';
$count = 1;
foreach ($result->results->Item as $r) {
echo '<div class="item">';
echo '<img class="cover" src="' . $r->MediumImage->URL . '"/>';
echo '<div class="data">';
echo $count . '. ';
echo '<a href="' . $r->DetailPageURL . '">' .
$r->ItemAttributes->Title . '</a>';
echo ' - '. $r->ItemAttributes->Author . '<br/>';
echo 'Amazon.com Sales Rank: ' . $r->SalesRank . '<br/>';
echo 'Amazon.com Price: ' .
$r->ItemAttributes->ListPrice->FormattedPrice . '';
echo '</div></div>';
$count++;
}
?>
</body>
</html>
清单7使用ISBN键作为公分母结合了前面的两个查询,以产生包含书名,作者,图像,价格和销售排名的综合结果。 然后,对该结果进行解析和处理以生成HTML页面( 图14 )。
图14.畅销书籍清单,以及通过YQL组合的产品数据
注意,在清单7中 ,内部查询专门仅检索畅销书列表上的书的ISBN-10号。 因为此信息是树中的几个节点,所以点符号用于向查询解析器指示所需节点的确切层次位置。 将唯一过滤器应用于外部查询时,将使用类似的技术,点标记用于指示要用来过滤结果的字段。
结论
如这些示例所示,YQL是Web应用程序开发人员的强大工具:它为不同的Web服务提供了统一的界面,从而启用了类似SQL的标准查询机制,从而加快了开发速度,并减少了有关目标服务的信息。 您可以使用WHERE子句过滤YQL结果,并通过使用子选择来组合或“混搭”来自多个服务的数据。 将PHP及其强大的XML处理工具添加到公式中,您将获得组合,即使是最疲惫的Web开发人员也可以尝试!
本文中的示例仅触及到冰山一角。 您可以使用YQL做更多的事情,包括分页结果集。 从RSS,Atom,XML和HTML文档中提取数据; 以及使用CREATE和UPDATE查询添加和修改数据。 我将在本文的第二部分中介绍更多内容,因此请确保您很快回来。
翻译自: https://www.ibm.com/developerworks/opensource/library/x-yqlphp1/index.html
雅虎yql php