使用亚马逊浏览节点API进行有意义的操作
我有一个网站(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处理了一下:
从人类的角度看这个列表,你不需要知道书的具体内容,就能看出这个书单很可能是关于科幻和奇幻的。这主要是因为人眼能很快忽略掉一些无意义的分类,比如“自定义商店”和“小说完整”。
我尝试过去重分类列表,或者只看所有三本书都出现的分类,但数据还是不太靠谱。我很想听听大家的想法,看看我怎么才能把这些数据变得对用户有意义。
到目前为止,我最好的想法是扫描这些数据,并与一个硬编码的列表进行匹配。比如说:
如果“科幻与奇幻”的数量大于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 个回答
嗯……首先,现在这个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 & 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。当然,在插入这些类别之前,我会检查一下它们是否已经存在。
这样做的目的是每本书有一条记录,每个类别也有一条记录,并且在书籍和类别之间、类别之间建立尽可能多的链接。
这样的话,从类别中查找书籍会非常简单,反之亦然。
抱歉我说得有点长,但你的问题没有简单的答案。希望这对你有帮助。
伯纳德
我目前想到的最好办法就是扫描数据,然后和一个固定的列表进行匹配。比如说:
如果“科幻与奇幻”的数量大于3,那么就把它归类为科幻;如果“商业、金融与法律”的数量大于3,那么就把它归类为商业。
我觉得这个主意还不错吧?可以从亚马逊上抓取一些主要的书籍分类,然后和这些分类进行匹配。虽然这个方法不太优雅,但应该能奏效。
另外,你也可以考虑使用来自Google图书API的dc:subject数据?(不过我没用过,所以也不一定好用)。