使用亚马逊浏览节点API进行有意义的操作

3 投票
2 回答
2437 浏览
提问于 2025-04-16 09:39

我有一个网站(www.7bks.com),用户可以在上面创建书单。现在这个网站功能比较简单。我已经在使用亚马逊的API来获取书籍的信息、图片等内容。

我想做的是,利用亚马逊的API获取一些分类或标签的数据,这样用户就可以在我的网站上更方便地浏览书单。不过,遗憾的是,标签的API方法已经停止使用了。

最有可能用到的是亚马逊API中的BrowseNodes方法(http://docs.amazonwebservices.com/AWSEcommerceService/2005-10-05/ApiReference/BrowseNodesResponseGroup.html),但是从这个调用返回的数据看起来有点让人摸不着头脑。我希望我们能一起想办法,把这些数据弄明白。

这里有一个谷歌表格,展示了我获取的数据类型。我选择了一个样本书单(http://www.7bks.com/list/549002),然后把三本书通过BrowseNodes API处理了一下:

https://spreadsheets.google.com/ccc?key=0ApVjkgehRamudHd5SlNhYllPQkZDSDY1cllfQVBQM1E&hl=en&authkey=CN_MxoAO

从人类的角度看这个列表,你不需要知道书的具体内容,就能看出这个书单很可能是关于科幻和奇幻的。这主要是因为人眼能很快忽略掉一些无意义的分类,比如“自定义商店”和“小说完整”。

我尝试过去重分类列表,或者只看所有三本书都出现的分类,但数据还是不太靠谱。我很想听听大家的想法,看看我怎么才能把这些数据变得对用户有意义。

到目前为止,我最好的想法是扫描这些数据,并与一个硬编码的列表进行匹配。比如说:

如果“科幻与奇幻”的数量大于3,那么这个书单就是科幻的;
如果“商业、金融与法律”的数量大于3,那么这个书单就是商业的;

等等。

不过,这种方法比较死板,我希望能建立一些更灵活、更强大的东西。

欢迎任何建议。

我认为这是一个高层次的问题,所以不应该受到我调用API的方式的影响,但作为参考,我使用的是Python/Appengine/Webapp。

谢谢

汤姆

更新:经过一番努力,我终于解决了这个问题,达到了我满意的效果。其实并不复杂,我写了一些Python代码,完成了我想要的功能。欢迎大家改进我的代码或提供建议。

基本上,这段代码的逻辑是这样的:
1)在XML树中,节点(books > subjects)下的最底层节点是对书籍内容的最佳猜测。例如,对于这个链接:http://www.amazon.co.uk/Surface-Detail-Iain-M-Banks/dp/1841498939/,它返回的是“科幻”。太棒了。
2)通常,限制自己只看那些以(books > subject)开头的结果,会丢掉很多有用的信息。因此,
3)我尝试获取类似书籍的列表,并从中提取分类,如果失败了,我就直接获取原书的分类。

或许通过以下代码可以更好地解释:

#takes as input the xml output of the amazon api browsenodes call
def getcategories(xml):
    #fetches the names of all the nodes, stores them in a list
    categories = []              
    for book in xml.getElementsByTagName('BrowseNode'):
        category = get_text(book,'Name')
        categories.append(category)

    #turn the one list into a series of individual lists
    #each individual list should be a particular tree from browsenode
    #each list will end 'Books'
    #the first item in the list should be the bottom of the tree
    taglists = []
    while 'Books' in categories:
        find = categories.index('Books') + 1
        list = categories[:find]
        taglists.append(list)
        for word in list:
            categories.remove(word)

    #now, we only return the first item from a list which contains 'Subjects'        
    final = []    
    for tagset in taglists:
        while 'Subjects' in tagset:
            final.append(tagset[0])
            tagset.pop(tagset.index('Subjects'))
    return final

class Browsenodes(webapp.RequestHandler):
    def get(self):
        #get the asin of the target book
        asin = self.request.get('term')
        if book_title:
            #fetch the amazon key
            api = API(AWS_KEY, SECRET_KEY, 'uk', processor=minidom_response_parser)
            try:
                #try getting a list of similar books - note the response group set to browsenodes
                result = api.similarity_lookup(asin, ResponseGroup='BrowseNodes')
            except:
                #there aren't always a list of similar books, so as a failsafe just get the book I wanted.
                result = api.item_lookup(asin, ResponseGroup='BrowseNodes')
            final = getcategories(result)
            #turn it into a set to de-dupe multiple listings of the same category
            self.response.out.write(set(final))

给你一个输出的感觉:

书籍:
http://www.amazon.co.uk/Surface-Detail-Iain-M-Banks/dp/1841498939/

标签:
当代小说
产品
太空歌剧
科幻

http://www.amazon.co.uk/Godel-Escher-Bach-Eternal-anniversary/dp/0140289208/
心理学
数学史
数学逻辑
一般AAS
流行数学
科学、技术与医学
艺术与音乐
心灵哲学
亚马逊
数学
建筑与逻辑
当代哲学:1900-
逻辑
经典
物理学
形而上学
物理哲学
一般
技术
代数数论
人工智能
科学史

http://www.amazon.co.uk/Flatland-Romance-Dimensions-Dover-Thrift/dp/048627263X/
当代小说
数学哲学
一般AAS
流行数学
哲学
科学、技术与医学
心灵哲学
科幻
数学
当代哲学:1900-
代数数论
产品
经典
形而上学与超现实
神话与童话
拓扑学一般
主题
一般
理论方法
形而上学
人工智能
科学史

http://www.amazon.co.uk/Victoria-Condor-Books-Knut-Hamsun/dp/0285647598/
当代小说
文学小说
心理小说
一般AAS
经典
短篇小说

2 个回答

0

嗯……首先,现在这个API的日期是2011年8月1日。也许你可以看看更新的文档,这样对你会有帮助?广告产品API

对我来说,XML的结构非常清晰!

也许是因为,当我想认真理解某个答案时,我会把XML复制到Visual Studio的XML编辑器里,这样我可以打开和关闭节点。

它的结构大致是这样的:

  <BrowseNodes>
    <BrowseNode>...</BrowseNode>
      <BrowseNode>...</BrowseNode>
      <BrowseNode>...</BrowseNode>
      <BrowseNode>...</BrowseNode>
    </BrowseNodes>

然后在每个BrowseNode里面,会是这样的内容:

<BrowseNode>
      <BrowseNodeId>10399</BrowseNodeId>
      <Name>Classics</Name>
      <Ancestors>
        <BrowseNode>
          <BrowseNodeId>17</BrowseNodeId>
          <Name>Literature &amp; Fiction</Name>
          <Ancestors>
            <BrowseNode>
              <BrowseNodeId>1000</BrowseNodeId>
              <Name>Subjects</Name>
              <IsCategoryRoot>1</IsCategoryRoot>

注意“IsCategoryRoot”吗?往上查找没有意义,因为这个太笼统了,不值得使用。书籍的名称是“Subjects”,而电子书的名称是“Categories”,所以查看“IsCategoryRoot”这个元素似乎更有意义。

我不太确定你想做什么,也不太懂Python,但我对数据库有一些了解……我会获取书籍的ASIN标识符(这是亚马逊全球唯一的标识,意味着你可以在amazon.com、co.uk、fr、de等网站上查找同样的ASIN),把它放到一个表里,连同其他你觉得有用的数据,创建一个类别表,把它们的名称和ID放进去,然后再创建一个链接表,每个较低层级的BrowseNode都有一条记录,记录BrowseNodeID和书籍的ASIN。对于嵌套的BrowseNode(实际上是父节点或祖先),我会同时记录它们的子ID和自己的ID。当然,在插入这些类别之前,我会检查一下它们是否已经存在。

这样做的目的是每本书有一条记录,每个类别也有一条记录,并且在书籍和类别之间、类别之间建立尽可能多的链接。

这样的话,从类别中查找书籍会非常简单,反之亦然。

抱歉我说得有点长,但你的问题没有简单的答案。希望这对你有帮助。

伯纳德

2

我目前想到的最好办法就是扫描数据,然后和一个固定的列表进行匹配。比如说:

如果“科幻与奇幻”的数量大于3,那么就把它归类为科幻;如果“商业、金融与法律”的数量大于3,那么就把它归类为商业。

我觉得这个主意还不错吧?可以从亚马逊上抓取一些主要的书籍分类,然后和这些分类进行匹配。虽然这个方法不太优雅,但应该能奏效。

另外,你也可以考虑使用来自Google图书API的dc:subject数据?(不过我没用过,所以也不一定好用)。

撰写回答