在熔炉 - eBay Web 服务
eBay 的 Web 服务 API 允许程序搜索在线拍卖,但前提是程序员首先不会感到太沮丧。
在过去的几个月中,我们研究了互联网上两家最大公司 Amazon 和 Google 提供的 Web 服务。这些公司都在其业务核心拥有庞大的数据库。通过 Web 服务 API 向公众开放其中一些数据,他们使外部开发人员可以创建新的有趣的应用程序。我们不再需要编写“屏幕抓取器”程序来解析 Amazon 或 Google 生成的 HTML。现在,我们可以编写一个程序,精确地请求我们想要的数据,并以我们需要的格式接收它。
另一个主要的在线竞争者是 eBay,其在线销售数据库很可能是迄今为止最大的。eBay 最初只是一个在线拍卖网站,但近年来已远远超出这一点——拥有固定价格子公司 (Half.com)、主 eBay 网站上的固定价格销售(立即购买)和第三方“商店”,人们在其中以固定或可变价格出售各种商品。
几年来,eBay 一直为有兴趣访问其数据库的程序员运行开发人员计划。然而,直到最近,这个开发人员计划还要求开发人员付费才能参与。从商业角度来看,eBay 最初似乎很愚蠢,因为它放弃了对其销售数据库的访问权限,尤其是在开发人员计划显然需要花钱才能建立和维护的情况下。无论是由于来自 Amazon 和 Google 的压力,还是来自个人开发人员的压力,或者 eBay 只是认为它可以从额外的宣传和外部开发人员中受益,eBay 都取消了费用——使每个人都可以尝试这项服务。
本月,我们将研究 eBay Web 服务 API 的几个方面。该 API 非常丰富和广泛,无法完全讨论,因此我们将研究我认为大多数人会有兴趣使用的功能——即允许您搜索现有的 eBay 拍卖,查找感兴趣的商品。在本文结束时,您应该了解 API 的工作原理、如何编写使用 REST 搜索 eBay 数据库的程序,以及如何将该信息用于个人和业务需求。
Web 服务背后的想法非常简单。与其将 HTTP 事务视为对 HTML 文档的请求,为什么不将其视为远程过程调用呢?然后,HTTP 请求成为在远程服务器上调用过程的方法,URL 指示应调用哪个方法,HTTP 响应包含调用的结果。在几乎所有情况下,响应都是 XML 文档,允许调用的过程返回复杂的数据结构。
调用 Web 服务至少有三种不同的风格,eBay 都支持它们。SOAP 可能是最复杂的方法,在请求和响应中都使用 XML,但它也是最复杂的,并且最有可能遇到跨平台不兼容性。这部分是因为 SOAP 试图标准化可能需要的所有可能的方法调用、数据类型和场景——导致规范有些臃肿,并且在许多地方,供应商对如何最好地遵守规范存在分歧。
eBay 还支持使用所谓的 XML API 调用 Web 服务。由于 SOAP 也由 XML 组成,我发现这种术语有点令人困惑,但 Amazon 也以这种方式描述事物。因此,在有人创建有用的首字母缩写词或名称之前,我们都将坚持使用它。基于 XML 的 API 基本上是 SOAP 的精简版本,没有与之相关的太多开销,例如命名空间和高度指定的方法来编组复杂的数据结构。eBay 表示可以使用 XML 或 SOAP 访问其 Web 服务的全部功能。
如果我必须在 SOAP 和 XML 之间做出选择,我通常会使用 XML。但是 eBay 提供了第三个接口,它比 SOAP 和 XML API 更有限,但更容易使用。第三个选项称为 REST(代表性状态转移的缩写),任何熟悉 URL 的人都应该立即理解它的工作原理。参数在 URL 中传递,使用标准的 name=value 语法。因此,REST 调用看起来像 http://www.example.com/method?param1=value1¶m2=value2。
REST 调用仅用于搜索 eBay 的目录。如果您想监控销售情况、调整购物车、向您的商店添加商品列表,甚至向卖家和买家发送消息,则必须使用 XML 或 SOAP API。API 文档的大小说明了一切:eBay 的 REST 文档长 29 页,而 SOAP 和 XML API 的文档在每种情况下都超过 1,600 页。
因为我们正在构建的应用程序应该只搜索现有报价,而不是添加新商品出售,所以我们可以使用 REST API。REST API 使您可以更轻松地直接上手,并且它以更少的编程开销提供了所有功能。
在您可以使用 eBay 的 Web 服务之前,您首先必须注册。我现在要说一些我以前从未在撰写此专栏的历史中说过的话:我无法保证我在此处提供的说明会有效。我花了很多时间尝试在 eBay 的开发者系统中注册,但遇到了极其困难的时期,我担心本专栏的许多读者也会面临类似的挑战。
第一个令人困惑的问题是 eBay 有几个不同的计算机系统,每个系统都有自己的用户数据库。第一个 (www.ebay.com) 是主要的常规 eBay 系统,如果您曾在 eBay 上买卖过东西,那么您已经拥有该系统上的用户名和密码。
第二个系统 (www.sandbox.ebay.com),称为沙箱,是 eBay 开发人员可以测试其应用程序的地方,而无需用完其每月请求配额(在下面更详细地描述),也无需冒着损坏正在运行的在线商店的风险。您可以在沙箱内执行任何操作,包括创建新用户(以模拟与这些用户的交互),但数据库与主 eBay 网站是分开的。
最后,还有 eBay 开发者站点 (developer.ebay.com),它允许访问 API、应用程序认证和文档。访问此站点需要第三个用户名和密码。
我建议有抱负的 eBay 开发人员在所有这三个站点上注册——从主 eBay 站点开始,继续到开发者站点,最后到沙箱。从技术上讲,如果您的应用程序仅在生产 eBay 系统上使用,则无需在沙箱中注册。但是,我发现有很多地方 URL 错误地将我带到沙箱,而不是开发者站点,因此获得沙箱登录将是明智之举。我被发送到沙箱是因为它与开发者站点相同吗?因为错误?因为我的配置中出现了一些问题?我希望我能说出来;我花了很多时间试图弄清楚,只是想避免本文的读者感到痛苦。
部分混乱的原因是沙箱看起来和感觉都与常规 eBay 网站完全相同。这在很大程度上是一件好事,但这意味着区分沙箱和普通 eBay 网站的唯一方法是查看 URL。即使来自沙箱的确认电子邮件消息也与来自生产 eBay 网站的电子邮件通知相同。
一旦您拥有所有三个登录名,您需要生成一组生产密钥:开发者 ID、应用程序 ID 和证书 ID。这些 ID 唯一标识您和您的应用程序,尽管每个密钥的作用对我来说并不明显。(eBay 文档表明每个应用程序都有自己的密钥,但我无法弄清楚如何为单独的应用程序生成一组新密钥。)每个开发者可能只有一组这样的生产密钥。尽管术语应用程序 ID 暗示您创建的每个应用程序都应该有一个单独的密钥,但情况似乎并非如此。
如果您要使用 eBay 的生产系统,那么您需要认证您的应用程序。认证分为两个级别。其中一个称为自我认证,允许您每月向 eBay 的服务器发出最多 10,000 个请求。自我认证,顾名思义,要求您填写一个简短的基于 Web 的表格,描述您的应用程序。将表格提交到 eBay 的服务器后,您将收到一封电子邮件,指示您的应用程序已通过自我认证。此电子邮件消息包含一个 URL 链接,您可以从中获取您的生产密钥,以及一个您必须输入的代码才能检索这些密钥。
使用此确认码,然后您返回到 eBay 开发者站点,在其中输入它。这将生成您的三个生产密钥:devID、appID 和 certID(有时在文档中称为 AuthCert)。
如果您计划使用 XML 或 SOAP,那么这就是认证过程的结束;您的应用程序需要在 HTTP 请求标头中发送这些 ID。但我们正在使用 REST,它应该简化事情——尽管我们实际的方法调用最终将比 XML 和 SOAP 替代方案更简单,但如果我们想使用 REST,我们还没有完全完成我们的任务。
这是因为 REST 参数在 URL 中传递,并且 eBay 似乎(正确地)决定传递 devID、appID 和 certID 参数会显得丑陋且不必要。要使用 REST,必须创建一个 REST 令牌,它会基于三个生产密钥创建一个新的编码字符串。要生成 REST 密钥,请访问 REST 令牌站点,网址为 developer.ebay.com/tokentool。指示您要使用生产环境,您想要一个 REST 令牌,然后输入您的三个生产密钥。
然后,如果您像我一样,您会收到一条错误消息。尽管我尽了最大努力,但我无法通过每次尝试生成 REST 令牌时显示的 eBay 登录屏幕。不用说,此时我感到非常沮丧,我开始想知道一家数十亿美元的公司如何(以及为什么)让开发人员如此难以使用其 API。(相比之下,在决定使用 Google、Bloglines 和 Amazon API 后,我在大约 30 分钟内启动并运行。差异再明显不过了。)
我从来没有真正弄清楚发生了什么事。也许我没有登录 eBay,尽管我以为我已经登录了所有三个站点(主站点、沙箱和开发者站点)。也可能是我正在使用 Firefox,众所周知 Firefox 在注册方面存在问题。最后,我使用了不同的浏览器,只是为了获得 REST 令牌。eBay 开发者论坛上的一些消息表明,其他 Firefox 用户也遇到了类似的问题。这可能与 eBay 的一个 SSL 证书在几个月前过期有关,尽管我对此表示怀疑。在我看来,eBay 网站的登录部分需要更好的质量控制。
一旦您度过了注册噩梦,您就可以发出查询。REST API 文档齐全,使用起来非常简单。首先,让我们看一个简单的程序,看看我们可以找到多少与特定文本字符串匹配的内容。该程序如清单 1 所示,是用 Ruby 编写的,类似于过去几个月中介绍的一些 Amazon 和 Google 搜索程序。
清单 1. ebay-lookup.rb
#!/usr/bin/ruby require 'net/http' require 'rexml/document' if ARGV.length == 0 puts "#{$0}: You must enter at least one argument." exit end output = "" # Iterate through each of our arguments ARGV.each do |query_string| output << "Searching for: #{query_string}\n" # Put together an eBay parameter string ebay_params = {'CallName' => 'GetSearchResults', 'RequestToken' => 'XXX', 'RequestUserId' => 'YYY', 'Schema' => 1, 'ItemTypeFilter' => 3, 'SearchInDescription' => 1, 'StoreSearch' => 3, 'DetailLevel' => 3, 'Query' => query_string}.map {|key,value| "#{key}=#{value}"}.join("&") # Ask eBay what it knows about our query_string ebay_response = Net::HTTP.get_response('rest.api.ebay.com', '/restapi?' << ebay_params) xml = REXML::Document.new(ebay_response.body) # Get basic information how_many_matches = xml.root.elements["PaginationResult/TotalNumberOfEntries"].text output << "Number of matches: #{how_many_matches}\n" end # Show everyone what we've learned puts output
该程序首先检索我们的搜索参数,这些参数自动放置在 ARGV 变量中。我们遍历 ARGV 的每个元素,调用每个单独的参数 query_string。然后,我们使用哈希来创建一组易于理解的名称-值对,其中哈希键是参数名称,哈希值是参数值。然后,我们使用一点 Ruby 魔法将它们组合起来,首先使用 map 将它们变成对,然后使用 join 将这些对用 & 连接在一起。最后,我们得到了一个可以传递给 eBay 服务器的字符串。
在这个特定的示例中,我们使用 REST API 中的 Query 方法。Query 允许我们输入一个文本字符串,eBay 将搜索该字符串。当您使用 eBay 的 Web 服务时,eBay 多年来以某种有机方式发展壮大的方式变得显而易见。您必须明确指示是否要在商店以及拍卖中搜索。我们还必须指示我们是否想要拍卖商品、固定价格商品或两者兼而有之。因此,我们的示例搜索所有商店(因为 StoreSearch = 3)、拍卖和固定价格商品 (ItemTypeFilter = 3)、描述以及商品标题 (SearchInDescription = 1),并返回相当多的详细信息 (DetailLevel = 3)。
我们还指示我们想要 Schema = 1。这告诉 eBay 我们希望使用 eBay 的新 XML 架构接收响应,而不是现在已弃用的旧架构。
然后,我们获取 ebay_params,一个从我们的名称-值对创建的字符串,并将其传递给 Net::HTTP.get_response。这将使用适当的路径 (/restapi) 向 eBay 的服务器 (rest.api.ebay.com) 发送 HTTP 请求,后跟我们的名称-值对。
当我们收到响应时——我们的示例代码在此处假设我们确实收到了响应——我们期望它是以 XML 格式化的,并使用 Ruby 的内置 REXML 库对其进行解析。我们抓取 eBay 数据库中包含此搜索字符串的条目总数,并使用 text 方法从 <TotalNumberOfEntries> 标签之间提取文本。最后,程序显示其输出,向我们显示 eBay 上有多少商品包含此文本字符串。
API 相对较快,使我们能够在相对较短的时间内执行特定字符串的查找。也就是说,流行的搜索字符串可能比稀有词花费的时间长得多。在我的计算机上搜索 ISBN 花费了 1-2 秒,并指示有多少卖家提供该 ISBN 出售。毫不奇怪,搜索术语 auction 花费了 30 多秒才返回结果,并指示 29,458,603 位卖家在标题或描述中提到了该术语。显然,搜索词的选择,以及卖家的数量和搜索该词的文本数量,将对应用程序的性能产生重大影响。
eBay 的 API 使执行各种类型的布尔搜索成为可能。将两个词放在引号内(当然是 URL 编码的)允许您搜索短语。您可以通过用逗号链接两个词来在同一拍卖中搜索它们。
您还可以包含和排除特定的卖家。如果您是 eBay 上的卖家,您可能想查看您的所有商品——或您所有竞争对手的商品,忽略您的商品。这些功能使您可以更轻松地浏览复杂的 eBay 世界,eBay 在其中销售来自世界各地种类繁多的商品。
eBay 的 API,特别是对于 SOAP 和 XML,非常丰富和广泛。这是对我们在清单 1 的示例中使用的简单但有限的 REST API 的补充。但是,eBay 对元数据或有关每个列表的信息的标记相当有限,尤其是与 Amazon 相比时。这可能是因为这两个站点之间的差异。Amazon 作为一家拥有库存的供应商,知道并可以提取有关每个商品的尺寸、重量和 ISBN 的信息。相比之下,eBay 关于每个已售商品的唯一真实信息是其分类、要价(和竞标信息)以及用于描述它的文本。
SOAP 和 XML API 中有一个条款可以通过 ExternalProductID 查找商品,ExternalProductID 可以是 ISBN 或 UPC。但是,当涉及到描述每个对象的元数据时,Amazon 已经彻底击败了 eBay。
在注册和使用方面,Amazon 也更友好。Amazon 使注册和入门变得容易。它的论坛上到处都是友好的人,他们提供有用的建议。而且,它为其数据设置了相对简单的使用规则。
eBay 与 Amazon 的不同之处还在于它允许应用程序发出多少查询。Amazon 不限制查询数量,除非它说每个 IP 地址每秒不应超过一个查询。相比之下,eBay 对每个应用程序的查询限制为 10,000 个。但是,如果您通过更彻底的认证过程,向 eBay 提供有关您的应用程序、其工作方式以及您打算如何使用它的更多信息,则可以大幅提高此限制。
这些公司在返回多少结果方面也存在差异。eBay 的每个页面最多包含 400 个商品,而 Amazon 的每个页面最多包含 10 个商品。在这两种情况下,您都可以请求后续的“页面”数据,直到您获得有关与您的查询匹配的所有列表的信息。在这种情况下,eBay 的较大格式对于寻找可能从许多卖家那里获得的热门商品的人来说是一个显着的改进。
最后,eBay 提供了一个仪表板,显示您发出的哪些调用以及哪些调用不符合其兼容性规则。这是一个出色的功能——特别是它跟踪有多少查询成功和失败的部分。我不希望在调试完 REST 查询后,我的许多 REST 查询会失败,但这有可能发生。
最重要的是,我对与 Amazon 的 Web 服务有关的一切印象深刻得多。eBay 显然正在努力改进,提供广泛的文档、开发者论坛和提供付费支持的服务台。尽管如此,它仍然远远不如 Amazon 提供的服务。而且,尽管它们不具有直接可比性,但它们也不如 Google 在 Web 服务领域提供的服务。
话虽如此,eBay 是电子商务领域的主要参与者,访问其数据很可能值得您在使用它时遇到的痛苦。此外,一旦您克服了注册障碍,您可能会在一段时间内只使用少数几个 API 调用,并进行细微的调整和更改。
eBay 最近对其开发者计划的更改是值得欢迎的进步。凭借三个接口(SOAP、XML 和 REST)以及开发人员可以使用的大量方法,可以从 eBay 的商店和拍卖中收集各种数据。不幸的是,这一切都是有代价的;由于元数据较少且注册过程不必要地令人困惑,eBay 提供的服务远不如它可能达到的水平那么令人印象深刻。
本文资源: /article/9066。
Reuven M. Lerner,一位长期的 Web/数据库顾问,目前是伊利诺伊州埃文斯顿西北大学学习科学专业的博士生。他和他的妻子最近庆祝了他们的儿子 Amotz David 的出生。