edo1z blog

プログラミングなどに関するブログです

Product Advertising APIのBrowseNodeLookupで本(和書)のBrowseNodeを全部取得する

Product Advertising APIのBrowseNodeLookupで本(和書)のBrowseNodeを全部取得したいと思います。

ここに、BrowseNodeLookupの説明が書いてあるんですがちょっと古くて、2013年2月現在では別の結果を返している気がするんですが。最新版ないんですかね?そもそもgoogle先生に聞くと、2011年頃に大幅な改訂がなされたとかで皆さん大騒ぎをしているんですがそれらの結果を反映した最新版が見つからないんですよね??英語だとあるんですかね。まあ自分で試して結果をみるのが一番確かだということで、試してみてます。

本(和書)のブラウズノードは、465610ですので、ここからどんどん下に掘っていきたいと思います。調べた感じですと、browsenodeを探して、その中にchildrenかancestorsが入ってたら飛ばす、両方とも入ってなかったら、そのbrowsenodeidを基に更に掘るという感じでどうだろうかと思っております。掘っても該当するbrowsenodeがなければそこが最下層であると認識します。僕は階層を明確化したいのではなく、最下層のbrowsenodeidの一覧を取得したいので、最下層であると判断されたら、browsenodelookupresponse > browsenodes > request > browsenodelookuprequest > browsenodeidを取得してリストに追加するというイメージでやってみたいと思います。いやいや今調べてたんだけど、そういうわけでもないんですね。なんなんだこのめちゃくちゃなresultは。まあ利用目的が違うとでもいいたいんだろうか。ドリルダウンで全ての属性を知りたいと思うことはあるだろうし、最下層の属性だけ抽出したいと思うこともあるだろうに。なぜこうもめんどくさい仕様になっているんだろうか。ということで、ancestorsが入ってなくてもancestorsであることもあることが分かりましたので、ancestorsを持っているタグ以降に出てくるものは全部ancestorsであるという条件も前提にいれましょう。

さて、BrowseNodeLookupで45610をみて、該当するidをforでBrowseNodeLookupすることを繰り返してみましょー。

class GetBrowseNode(webapp2.RequestHandler):
    def get(self):         
            browseNodeWasyo = 465610
            resultList = browseNodeCheck(browseNodeLookup(browseNodeWasyo))
            templateValues = {'result':resultList} 
            template = jinja_environment.get_template('index.html')
            self.response.out.write(template.render(templateValues))

def browseNodeLookup(browseNodeId):
    pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
    xml = pyzon.BrowseNodeLookup(browsenode_id=str(browseNodeId))
    xml = urllib.unquote(xml)
    soup = BeautifulStoneSoup(xml)
    return soup

def browseNodeCheck(result):
    resultList = []
    
    if not result.errors:
        browsenodes = result.browsenodelookupresponse.browsenodes
        ancestorsList = browsenodes.findAll('ancestors')
        for ancestors in ancestorsList:
            if ancestors.browsenode: ancestors.extract()
        browseNodeList = browsenodes.findAll('browsenode')
        childrenCnt = 0
        AncestorsCnt = 0
        
        for node in browseNodeList:
            if not node.children and not node.ancestors:
                if AncestorsCnt > 0:
                    AncestorsCnt += 1
                else:
                    time.sleep(1)
                    resultList += browseNodeCheck(browseNodeLookup(node.browsenodeid.contents[0]))
            else:
                if node.ancestors:
                    AncestorsCnt += 1
                elif node.children:
                    childrenCnt += 1
                    
        if  (childrenCnt + AncestorsCnt) == len(browseNodeList):
            browsenodeid = browsenodes.request.browsenodelookuprequest.browsenodeid.contents[0]
            resultList.append(int(browsenodeid))
            logging.debug(u'browsenodeid追加: ' + str(browsenodeid))
        
    else:
        code = result.errors.error.code.string
        message = result.errors.error.message.string
        logging.error(u'AmazonError! code: ' + code + u' message: ' + message)
    
    return resultList


これは、GAE、Pythonでつくっていまして、ライブラリは、PyzonとBeautifulSoupを使ってます。ブラウズノードを確認して、まだ下が有る場合はどんどん突き進み、もう下がない場合はリストにbrowsenodeidを追加するようになっております。再帰してます。ただ、これだと超時間がかかりまして、GAEのローカル環境ですと途中でエラーになりました。いずれにしてもこれを毎日のように実行すると考えるとかなり非現実的です。再帰が使える状況って限られますね。よって、都度都度検索型に変えようと思います。失礼いたしました。