IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  SOA and Web services  >

Python Web 服务开发者: 现实世界,第二部分

Amazon.com Web API

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

Scott Archer, 软件架构师, GlowingOrb Inc.
Uche Ogbuji, 首席顾问, Fourthought Inc.

2004 年 2 月 01 日

本专栏涵盖了可以用于 Web 服务处理的主要 Python API,通过简单的客户端和服务器的使用演示了基本的工具和方法。所有这些都为使用现实世界 Web 服务打下了基础。“现实世界”的第一部分展示了如何使用 Google Web 服务 API 搜索 Web。现在第二部分要进一步深入,将那些工具与理解应用到更为复杂的现实世界 Web 服务应用程序中去。该问题将以 Amazon.com 的 Web API 为重点 -- 作者将向您展示如何通过 SOAP 连接到 Amazon.com,这样您就可以程序化地搜索 Amazon.com 的大量目录。此外,作者还将向您展示如何在 GUI 中包装 Web 服务代码。

Amazon Web 服务 API

Amazon.com, 常称为世界上最大的存储库,它已经开放了产品的所有目录,以便采用 SOAP 或 REST (HTTP 之上的 XML)技术直接集成到其他的 Web 站点中去。通过各种合作项目,合作者与第三方供应商都可以从中赚取介绍费,并且管理详细目录,搜索产品信息,以获取有竞争力的价格。为了展示 Amazon.com Web 服务 API 的一些用途,我们将向您演示如何创建 GUI 工具,这种工具使您能够在 Amazon.com 目录的各种产品类别中搜索相似类型的条目。由于它是典型的 Web 服务提供者,所以由 Amazon.com 开发者工具包提供的示例和工具不包括 Python 绑定或库。即使这样也不用担心 —— 通过 Python 使用 Amazon API 是非常简单易懂的,甚至有可能比一般的语言和工具都还要简单。





回页首


设置

对于这个项目,我们将使用 Python 2.3 精心地设计我们的工具;0.10.4 版本的 SOAPpy 用来代理和编组 API,我们将使用 wxPython 工具包来创建 GUI。0.10.3 版本之后的 SOAPpy 还要依赖于 IEEE 754 浮点处理程序包 fpconst(当前版本 0.6.0)。这很有可能包括在以后的 Python 发行版本中。请参阅 参考资料以获得下载这些工具的链接。

登录到 Amazon.com Web 服务站点(请参阅 参考资料),下载免费的开发者工具包,并且进行注册,以获取一个免费开发者令牌,您需要这个令牌来将每个方法调用传送到 Web 服务 API。在我们继续创建工具之前,让我们先测试一下 Amazon API。我们在 Amazon.com 上执行关键字搜索功能,以查找与“spotted owl”有关的书籍。通过深入分析 API 的 WSDL ,我们找到了一种合适的方法, KeywordSearchRequest (请参见 清单 1)。

清单 1. Amazon Web 服务 API WSDL 的专家展示 KeywordSearchRequest.
				
          
...
<message name="KeywordSearchRequest">
    <!-- Messages for Amazon Web APIs -->
    <part name="KeywordSearchRequest" type="typens:KeywordRequest"/>
</message>
<message name="KeywordSearchResponse">
    <part name="return" type="typens:ProductInfo"/>
</message>
<xsd:complexType name="KeywordRequest">
<xsd:all>
    <xsd:element name="keyword" type="xsd:string"/>
    <xsd:element name="page" type="xsd:string"/>
    <xsd:element name="mode" type="xsd:string"/>
    <xsd:element name="tag" type="xsd:string"/>
    <xsd:element name="type" type="xsd:string"/>
    <xsd:element name="devtag" type="xsd:string"/>
    <xsd:element name="sort" type="xsd:string" minOccurs="0"/>
    <xsd:element name="locale" type="xsd:string" minOccurs="0"/>
    <xsd:element name="price" type="xsd:string" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="ProductInfo">
<xsd:all>
    <xsd:element name="TotalResults" type="xsd:string" minOccurs="0"/>
    <!-- Total number of Search Results -->
    
    <xsd:element name="TotalPages" type="xsd:string" minOccurs="0"/>
    <!-- Total number of Pages of Search Results -->
    
    <xsd:element name="ListName" type="xsd:string" minOccurs="0"/>
    <!-- Listmania list name -->
    
    <xsd:element name="Details" type="typens:DetailsArray" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
...  

			
      

KeywordSearchRequest 接受单个参数,包含查询所需参数的结构。显而易见,首先就是 keyword 参数。Amazon.com 以每页不超过 10 个条目的方式返回结果,这由 page 参数指定。其余的参数就不那么明显了。查阅 API 文档(是的,我们必须看看 WSDL 之外的东西),我们发现 mode 指定了产品种类,比如“书籍(books)”、“音乐(music)”、“dvd”或“厨房用具(kitchen)”——所用的术语必须与特定类别的列表相匹配。此处我们将使用的是美国(US)版本的 mode 。还有一种办法就是在 API 中包含 mode 的英国(UK)、德国(German)、日本(Japanese)版本 ——例如,各个条目分别就是“books-uk”、“books-de”、“books-jp”。 

 Amazon 的合作项目中的用户可以将他们的合作者 ID 放在 tag 参数中,有可能赚取与查询有关的购买的介绍费。所返回的每个条目的详细信息可以通过 type 参数来设置,允许值有“lite”或“heavy” 。最后一个参数(对 US 而言)就是 devtag ,它必须包含您的开发者令牌。剩下的参数很简单易懂,我们这里就不再介绍了。

一旦成功地完成查询,就会返回 KeywordSearchResponse ,或者如果查询没有找到匹配的条目,就会抛出一个 SOAP Fault,其中包含说明情况的消息。实际响应信息是包装在 ProductInfo 结构中的。除了显而易见的 TotalResultsTotalPages 之外,我们还对 Details 组件感兴趣。对于每个结果, DetailsArray 中的 Details 结构的内容都依赖于模式产品种类,正如 API 文档中所指定的。(请参阅 参考资料)。

现在,让我们来编写一个执行测试查询的简单应用程序(请参见 清单 2)。

清单 2. amazon_soap_test.py —— 用于测试 Amazon Web 服务 API 的简单 Python 代码。
				
           
#!/usr/bin/python
import SOAPpy
url = 'http://soap.amazon.com/schemas3/AmazonWebServices.wsdl'
proxy = SOAPpy.WSDL.Proxy(url)
# show methods retrieved from WSDL
print '%d methods in WSDL:' % len(proxy.methods) + '\\n'
for key in proxy.methods.keys():
    print key
print
# search request
_query = 'spotted owl'
request = { 'keyword':  _query, 
            'page':     '1', 
            'mode':     'books', 
            'tag':      '', 
            'type':     'lite', 
            'devtag':   'INSERT YOUR TOKEN HERE' }
results = proxy.KeywordSearchRequest(request)
# display results
print 'Amazon.com search for  " ' + _query + ' "\\n'
print 'total pages of results (max 10 per page): ' + str(results.TotalPages)
print 'total results: ' + str(results.TotalResults) + '\\n'
# only show first result here
if (results.TotalResults > 0):
    print 'displaying first result (of %s):\\n' %results.TotalResults
    details = results.Details[0]
    
    # we must use the _keys() method of SOAPpy Types.py for arrayType
    for key in details._keys():
        print key + ': ' + details[key]
    print

			
      

在导入 SOAPpy 库之后,我们使用这个库来为发布在各自站点上的 WSDL 中的 Amazon Web 服务 API 创建一个代理。SOAPpy 中的 WSDL.Proxy 为访问通过 WSDL 定义的 API 提供了功能强大的工具。在使用代理进行任何调用之前,我们先将 Amazon API 中公开的方法列表打印出来。这样一来,正如 WSDL 中所指定的和 API 文档中所描述的一样,调用 SOAP 方法就与构造合适参数并在代理对象上调用方法一样简单了。在本例下,我们创建一个 request 结构,然后使用适当的参数将这个结构填充到我们的查询中去。

注意,我们使用的是 SOAPpy 的 Types.py 模块中的 _keys() 方法,因为结果的详细情况(details)组件是 SOAP arrayType ,它通常映射到 Python 字典。

0.10.4 版本的 SOAPpy 在试着从 URL 加载的 WSDL 定义时存在着一个错误。(请参见 清单 3)。

清单 3. 使用 SOAPpy 从 URL 加载 WSDL 的跟踪信息
				
        
Traceback (most recent call last):
  File "./amazon_soap_test.py", line 21, in ?
    proxy = SOAPpy.WSDL.Proxy(url)
  File "/usr/lib/python2.3/site-packages/SOAPpy/WSDL.py", line 61, in __init__
    self.wsdl = reader.loadFromStream(stream)
  File "/usr/lib/python2.3/site-packages/SOAPpy/wstools/WSDLTools.py", 
  line 28, in loadFromStream
    wsdl.location = file.name
AttributeError: addinfourl instance has no attribute 'name'

			
      

直接从 URL 加载 WSDL 需要能够快速修复 SOAPpy 0.10.4 中的 WSDL.py 模块——如 清单 4 所示——您主要是将赋值调用从 reader.loadFromStream(stream) 更改到了 reader.loadFromURL(wsdlsource)

清单 4. 展示快速修复 SOAPpy 0.10.4 中的 WSDL.py 的不同之处
				
           
60,61c60
<                 stream = urllib.urlopen(wsdlsource)
<                 self.wsdl = reader.loadFromStream(stream)
---
>                 self.wsdl = reader.loadFromURL(wsdlsource)   

			
      

瞧,行了!我们的小测试应用程序正常工作了(请参见 清单 5)。当然了,不修改 SOAPpy,我们也能使用浏览器从 Amazon.com 中检索到 WSDL 文件(请参阅 参考资料),然后从本地文件中进行加载——这对 SOAPpy 的 0.10.4 版本同样是有效的。

清单 5. amazon_soap_test.py 的输出结果。
				
           
[scott@baal amazon_api]$ python amazon_soap_test.py
26 methods in WSDL:
BlendedSearchRequest
WishlistSearchRequest
ClearShoppingCartRequest
MarketplaceSearchRequest
BrowseNodeSearchRequest
SimilaritySearchRequest
SkuSearchRequest
SellerSearchRequest
SellerProfileSearchRequest
ActorSearchRequest
AsinSearchRequest
ListManiaSearchRequest
AuthorSearchRequest
GetShoppingCartRequest
PowerSearchRequest
ExchangeSearchRequest
DirectorSearchRequest
TextStreamSearchRequest
ModifyShoppingCartItemsRequest
KeywordSearchRequest
ArtistSearchRequest
UpcSearchRequest
GetTransactionDetailsRequest
AddShoppingCartItemsRequest
RemoveShoppingCartItemsRequest
ManufacturerSearchRequest
Amazon.com search for  " spotted owl "
total pages of results (max 10 per page): 6
total results: 52
displaying first result (of 52):
Asin: 0060248912
ImageUrlSmall: http://images.amazon.com/images/P/0060248912.01.THUMBZZZ.jpg
ProductName: There's an Owl in the Shower
ListPrice: $14.95
Availability: THIS TITLE IS CURRENTLY NOT AVAILABLE. 
If you would like to purchase this title, we recommend 
that you occasionally check this page to see if it has become available.
ReleaseDate: September, 1995
Catalog: Book
<SOAPpy.Types.typedArrayType at 1084200524>
Manufacturer: Harpercollins Juvenile Books
Url: http://www.amazon.com/exec/obidos/ASIN/0060248912/?dev-t=
D1V63VYIH286CL%26camp=2025%26link_code=sp1
UsedPrice: $1.25
ImageUrlMedium: http://images.amazon.com/images/P/0060248912.01.MZZZZZZZ.jpg
ImageUrlLarge: http://images.amazon.com/images/P/0060248912.01.LZZZZZZZ.jpg
OurPrice: $14.95

			
      

清单 5 的第一部分中您可以看到,有 26 个请求方法定义在 Amazon API 的 WSDL 中。关于参数和返回结构的详细消息可以在 Amazon 中的 WSDL 和开发者文档中找到。尽管代码无疑可以被扩展以执行更为高级的查询,但是在本例中我们仅使用 KeywordSearchRequest 方法。





回页首


完全不同之处

现在我们可以利用关于 Amazon Web 服务 API 的知识来做些有用的事情。Python 经常被很多人责备,认为它在 GUI 创建的领域中跟不上其他理解 SOAP 的语言。其实,利用 Python 可以很容易地创建出强大且真正意义上跨平台的用户界面。为了证明这一点,我们将使用 Python 和 wxPython UI 库来创建一个小 GUI 应用程序,以便执行关键字搜索来查找书籍(book)、音乐(music)和 dvd。 图 1展示了我们运行中的 GUI。


Amazon.com SOAP 部件

选定产品种类(在 Amazon 中也称为 模式),输入您的关键字查询(各个关键字由空格格开)并点击‘Search Amazon’按钮。您的网络集线器上的灯就会开始闪烁,几秒钟后,‘Query Results’列表框就将添满。选择一个条目来查看详细信息,如果可能的话,查看条目的图像。为了简单起见,我们只获取不超过 10 个条目的第一页。这很容易扩展。

清单 6 展示了我们的应用程序代码。基本上,它是我们的测试应用程序,嵌入到一个用户界面中,并扩展为搜索音乐(music)和 dvd,并显示所获取条目的详细信息以及图像。

清单 6. amazon_widget.py —— Amazon.com 搜索 GUI 的 Python 代码.
				
           
#!/usr/bin/python
# setup SOAP proxy
import SOAPpy
file = 'AmazonWebServices.wsdl'
amazon = SOAPpy.WSDL.Proxy(file)
# import the wxPython libraries
import wxPython.wx
from wxPython.wx import *
import urllib
# developer token for amazon api
DEV_TOKEN = 'INSERT YOUR TOKEN HERE'
 
# event ids
ID_SEARCH   = 100
ID_SELCHG   = 101
#------------------------------------------------------------------------------
# amazonWidgetFrame - the main window for our app
#------------------------------------------------------------------------------
class amazonWidgetFrame(wxFrame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(500, 475))
        
        # add a status bar
        self.CreateStatusBar()
        self.SetStatusText("")
        
        # add other widgets to frame
        frame_box = wxBoxSizer(wxVERTICAL)
        
        # query part
        query_box = wxBoxSizer(wxHORIZONTAL)
        
        # set the mode (product line to search)
        mode_box = 
        wxStaticBoxSizer(wxStaticBox(self, -1, "Product Line"), wxVERTICAL)
        self.mode_books = 
        wxRadioButton(self, -1, "books", 
                                        wxDefaultPosition, wxDefaultSize, wxRB_GROUP)
        self.mode_music = wxRadioButton(self, -1, "music", 
                                        wxDefaultPosition, wxDefaultSize)
        self.mode_dvds = wxRadioButton(self, -1, "dvd", 
                                        wxDefaultPosition, wxDefaultSize)
        mode_box.Add(self.mode_books, 0, wxLEFT|wxRIGHT, 10)
        mode_box.Add(self.mode_music, 0, wxLEFT|wxRIGHT, 10)
        mode_box.Add(self.mode_dvds, 0, wxLEFT|wxRIGHT, 10)
        query_box.Add(mode_box, 0, wxALL, 5)
        
        # edit and button
        qtext_box = 
        wxStaticBoxSizer(wxStaticBox(self, -1, "Enter Query"), wxHORIZONTAL)
        self.search_text = 
        wxTextCtrl(self, -1, "python web", wxDefaultPosition, (200, -1))
        qtext_box.Add(self.search_text, 1, wxALL, 5)        
        qtext_box.Add(wxButton(self, ID_SEARCH, "Search Amazon"), 0, wxALL, 5)
        query_box.Add(qtext_box, 0, wxALL, 5)
        frame_box.Add(query_box, 0, wxBOTTOM, 5)
        # results part
        results_box = wxBoxSizer(wxHORIZONTAL)
        
        # details        
        details_box = 
        wxStaticBoxSizer(wxStaticBox(self, -1, "Query Results"), wxVERTICAL)
        self.results_list = 
        wxListBox(self, ID_SELCHG, wxDefaultPosition, (300,175),
                                 [], wxLB_ALWAYS_SB)
        details_box.Add(self.results_list, 0, wxALL, 5)        
        
        hbox = wxBoxSizer(wxHORIZONTAL)
        tbox = wxBoxSizer(wxVERTICAL)
        tbox.Add(wxStaticText(self, -1, "Author/Artist: "), 0, wxLEFT, 5)
        tbox.Add(wxStaticText(self, -1, ""), 0, wxLEFT, 5)
        hbox.Add(tbox, 0)
        hbox.Add(20,0,1)
        self.authors = wxListBox(self, -1, wxDefaultPosition, (200,65), [])
        hbox.Add(self.authors, 0, wxALIGN_RIGHT)
        details_box.Add(hbox, 0, wxBOTTOM, 5)        
        hbox = wxBoxSizer(wxHORIZONTAL)
        hbox.Add(wxStaticText(self, -1, "Release Date: "), 0, wxLEFT, 5)
        self.release_date = wxStaticText(self, -1, "                  ", 
        wxDefaultPosition, wxDefaultSize)
        hbox.Add(self.release_date, 0)
        details_box.Add(hbox, 0)        
        
        hbox = wxBoxSizer(wxHORIZONTAL)
        hbox.Add(wxStaticText(self, -1, "List Price: "), 0, wxLEFT, 5)
        self.list_price = wxStaticText(self, -1, "           ", 
        wxDefaultPosition, wxDefaultSize)
        hbox.Add(self.list_price, 0)
        details_box.Add(hbox, 0)        
        
        hbox = wxBoxSizer(wxHORIZONTAL)
        hbox.Add(wxStaticText(self, -1, "Amazon.com Price: "), 0, wxLEFT, 5)
        self.amazon_price = wxStaticText(self, -1, "           ", 
        wxDefaultPosition, wxDefaultSize)
        hbox.Add(self.amazon_price, 0)
        details_box.Add(hbox, 0, wxBOTTOM, 5)        
        results_box.Add(details_box, 0, wxALL, 5)        
        
        # image
        image_box = 
        wxStaticBoxSizer(wxStaticBox(self, -1, "Product Image"), wxHORIZONTAL)
        
        # inline class for drawing our product image 
        class amazonImagePanel(wxPanel):
            def __init__(self, parent, id, position, size):
                wxPanel.__init__(self, parent, id, position, size)
                self.parent = parent        
                self.image = None
                EVT_PAINT(self, self.OnPaint)
            def OnPaint(self, evt):
                dc = wxPaintDC(self)
                if self.image:
                    bitmap = wxBitmapFromImage(self.image)
                    dc.DrawBitmap(bitmap, 0, 0, false)
        
        self.image_canvas = amazonImagePanel(self, -1, wxDefaultPosition, (130,150))
        image_box.Add(self.image_canvas, 1, wxALL, 5)
                
        results_box.Add(image_box, 0, wxALL, 5)
        
        # finally...
        frame_box.Add(results_box, 0, wxTOP, 5)
        
        # add main sizer
        self.SetSizer(frame_box)
        
        # set event handlers
        EVT_BUTTON(self, ID_SEARCH, self.OnSearch)
        EVT_LISTBOX(self, ID_SELCHG, self.OnSelectionChange)
        
    #---------------------------------------------------------------------
    # build and call query - if returns OK, set the GUI fields
    #---------------------------------------------------------------------
    def OnSearch(self, event):
        # fetch mode and query text
        query = self.search_text.GetValue()
        self.mode = 'books'
        if self.mode_music.GetValue():
            self.mode = 'music'
        elif self.mode_dvds.GetValue():
            self.mode = 'dvd'        
        request = { 'keyword': query, 'page': '1', 'mode': self.mode, 
                    'tag': '', 'type': 'lite', 'devtag':  DEV_TOKEN }
        # do the query
        try:
            tmp_results = amazon.KeywordSearchRequest(request)
        except SOAPpy.faultType:
            self.SetStatusText('There were no exact matches for the search')
        else:                    
            self.results = tmp_results
            self.SetStatusText('total results: ' + str(self.results.TotalResults) +
                               '  (only showing first 10)')
            # load up results box             
            items = []
            images = []
            for detail in self.results.Details:
                items.append(detail['ProductName'])
                images.append(detail['ImageUrlMedium'])
            self.results_list.Set(items)
            self.results_list.SetFirstItem(0)
            
            # clear displayed image
            self.authors.Set([])
            self.release_date.SetLabel('')                
            self.list_price.SetLabel('')
            self.amazon_price.SetLabel('')
            self.image_canvas.image = None
            self.image_canvas.Refresh()
            # cache images
            self.loadImages(images)
            
            
    #---------------------------------------------------------------------
    # whenever the product selection changes, update other fields
    #---------------------------------------------------------------------
    def OnSelectionChange(self, event):
        # fetch selected item from results
        sel = self.results_list.GetSelections()
        detail = self.results.Details[sel[0]]
        
        # set the author/artist field
        items = []
        if self.mode == 'books':
            if 'Authors' in detail._keys():
                authors = detail['Authors']
                for author in authors:
                    items.append(author)
                self.authors.Set(items)
        elif self.mode == 'music':
            if 'Artists' in detail._keys():
                authors = detail['Artists']
                for author in authors:
                    items.append(author)
                self.authors.Set(items)
        elif self.mode == 'dvd':
            # only in 'heavy' search type
            if 'Directors' in detail._keys():
                authors = detail['Directors']
                for author in authors:
                    items.append(author)
                self.authors.Set(items)
        # set release date and pricing fields
        if 'ReleaseDate' in detail._keys():
            self.release_date.SetLabel(detail['ReleaseDate'])                
        if 'ListPrice' in detail._keys():
            self.list_price.SetLabel(detail['ListPrice'])
        if 'OurPrice' in detail._keys():
            self.amazon_price.SetLabel(detail['OurPrice'])
        
        # fetch image
        image_name = 'image_tmp_' + str(sel[0]) + '.jpg'
        self.image_canvas.image = wxImage(image_name)
        self.image_canvas.Refresh()
        
        
    #---------------------------------------------------------------------
    # retrieve from amazon.com and temporarily save images
    #---------------------------------------------------------------------
    def loadImages(self, images):
        i = 0
        for url in images:
            image_name = 'image_tmp_' + str(i) + '.jpg'
            pic = urllib.urlopen(url)
            img = pic.read()
            pic.close()
            f = open(image_name,'wb')
            f.write(img)
            f.close()
            i = i+1
                
#------------------------------------------------------------------------------
# simple wxApp
#------------------------------------------------------------------------------
class amazonWidgetApp(wxApp):
    def __init__(self, parent):
        wxApp.__init__(self, parent)
        
    def OnInit(self):
        # start GUI
        frame = amazonWidgetFrame(NULL, -1, "Amazon.com SOAP Widget")
        frame.Show(true)
        self.SetTopWindow(frame)
        return true
#------------------------------------------------------------------------------
# run this when module gets called
#------------------------------------------------------------------------------
if __name__ == '__main__':
       
    # must call this for wxImage to load JPEGs
    wx.wxInitAllImageHandlers()
    
    app = amazonWidgetApp(0)
    app.MainLoop()

			
      

我们选择使用 wxPython 库而不使用 TkInter 或者 Python 中所包含的其他更小的 GUI 工具包。在 wxWindows 库周围主要就是 Python 包装,它是一种非常快速以及完完全全跨平台的窗口操作框架(windowing framework)。为了演示创建 GUI 的目的,我们手工操作控制布局,而不使用可用的 wxWindows WYSIWYG 布局工具,比如 wxDesigner。这样就形成了 amazonFrame.__init__( ) 方法中的大量代码。我们广泛应用 wxBoxSizer 控件来对有趣的控件的布局。

需要引起注意的是,由于 wxWindows 事件环(event loop)的线程问题,需要在导入 wxPython 之前导入 SOAPpy 并创建代理。而且,因为启动执行的原因,我们要从本地文件导入而不是从 Amazon.com 站点导入 WSDL。

当运行应用程序时,就创建了 amazonWidgetApp 并调用 MainLoop( ) 来启动事件环。请留意 amazonWidgetFrame__init__( ) 方法内部定义的 amazonImagePanel 类。我们定义了两个主要的事件处理程序: OnSearch( ) 用于处理按下 “Search Amazon” 按钮, OnSelectionChange( ) 用于处理 “Query Results” 列表框中的条目选择。

OnSearch( ) 获取 GUI 中的 模式设置,构建请求结构,然后调用 amazon SOAPpy 代理上的 KeywordSearchRequest SOAP 方法。SOAP 方法调用是在 try - except 块中执行的,一般来说,这种方式比较好,但这里我们这样做只是捕捉 SOAP.faultType 异常。我们应该检查异常类型,但此处我们将假定它意味着没有找到相应结果。如果所有这一切都正常,我们就保留 amazonWidgetFrame 中的 self.results 属性,填充“Query Results”列表框,然后从 Amazon.com 中获取结果详细信息中所引用的全部图像。

OnSelectionChange( )self.results 中获取适当的详细信息并将各自的组件填充到 amazonWidgetFrame 上去,最后加载正确的图像副本并执行重新布局。



参考资料



作者简介

作者相片

Scott Archer 是一位软件架构师,也是 GlowingOrb, Inc. 的创始人。他是一名软件工具开发人员,主要研究模型驱动的解决方案与核心业务流程的集成。Archer 在香港大学获得了 Computational Molecular Biology 的 M.Phil 学位。您可以通过 scott.archer at glowingorb.com 与 Archer 联系。


作者相片

Uche Ogbuji 是一名顾问以及 Fourthought Inc. 的创始人,一名软件供应商与顾问,他专长于企业知识管理应用程序的 XML 解决方案。 Fourthought 开发出了 4Suite,XML 中间件的开放源码平台。您可以通过 uche.ogbuji@fourthought.com 与 Ogbuji 联系。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款