Amazon API を叩いてランキングを取得してみた話

どうも片倉です。
遊星ジャーナルをAmazonで刊行して一週間が経ちました。
そうするとどうしても気になるのがランキング。
Kindle本の「SF・ホラー・ファンタジーの売れ筋ランキング」

手動で定点観測してたらクッソ面倒だったのでAmazonAPIを叩いてランキングを取得するPythonコードを書きました。

手動編

しばらくランキングを手動で定点観測してました。

・遊星ジャーナル『大いに偉大なる重力の遊星』のAmazonランキングメモ
 販売開始日:2017年6月8日
 購入可能日:2017年6月11日
 「SF・ホラー・ファンタジー」カテゴリ(2017年6月12日13時に反映)

 カテゴリ新着ランキング:2017年6月12日13時より2017年6月14日16時頃まで1位をほぼ維持。
 以降は時間帯により2位との入れ替わりあり。

 カテゴリ売れ筋ランキング、新着ランキング:
 2017年6月12日13時時点で4位、新着1位
 2017年6月13日23時時点で25位、新着1位
 2017年6月14日13時時点で20位、新着1位
 2017年6月15日15時時点で10位、新着1位
 2017年6月16日14時時点で37位、新着2位
 2017年6月17日14時時点で24位、新着1位

おかげさまで好評を頂いております。
2017年6月18日の11時時点では18位、新着一位でした。

ですが。
手動とか馬鹿馬鹿しい。

と思ったのでPythonAmazon APIを叩いてランキングを取得するコードを書きました。
Amazon API の叩き方はググってください。
パラメータを何にすればええのん?という方はProduct Advertising API Scratchpadで色々試してみればいいと思います。

自動化編

というわけで久々にNetbeansを起動したのだった。
環境は
LinuxMint 18.1
Python 2.7.12 (いい加減世のライブラリは全て3に移行してくれ)

コードをPONと置いておきます。勝手に使って下さい。

# coding=utf-8
 
""" AmazonAPIをラップしてくれるやつ """
from bottlenose import api

""" XMLパーサ """
from bs4 import BeautifulSoup

""" 503エラー回避用 """
import urllib2

""" 503エラーが出たらsleepで待つ(APIは1秒に1回しか叩けない) """
import time

""" ご自分のアクセスキーとシークレットキーとアソシエイトタグをどうぞ """
AMAZON_ACCESS_KEY_ID="XXXXXXXXXXXXXXXXXX"
AMAZON_SECRET_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
AMAZON_ASSOC_TAG="XXXXXX-22"

""" 503エラーが出たらリトライ、それ以外のエラーは例外吐いて終了 """
def error_handler(err):
    ex = err['exception']
    if isinstance(ex, urllib2.HTTPError) and ex.code == 503:
        time.sleep(1.5)
        return True
    else:
        return false

""" カテゴリのおすすめ順を取得する """
def item_search(item_page, amazon, search_index="Books", response_group="SalesRank,Small", browse_node="2292700051"):    
    response = amazon.ItemSearch(
        SearchIndex=search_index, 
        BrowseNode=browse_node, 
        ItemPage=item_page, 
        ResponseGroup=response_group
        )

    time.sleep(1.5)

    return response.findAll('item')


""" カテゴリ売れ筋ランキングを取得する """
def browse_node_lookup(response_group="TopSellers", browse_node="2292700051"):    
    response = amazon.BrowseNodeLookup(
        BrowseNodeId=browse_node, 
        ResponseGroup=response_group
        )

    time.sleep(1.5)
    print response
    return response.findAll('topseller')


""" カテゴリ新着ランキングを取得する """
def new_release_lookup(response_group="NewReleases", browse_node="2292700051"):    
    response = amazon.BrowseNodeLookup(
        BrowseNodeId=browse_node, 
        ResponseGroup=response_group,
        )

    time.sleep(1.5)
    print response
    return response.findAll('newrelease')


def flatten(nested_list):
    """2重のリストをフラットにする関数"""
    return [e for inner_list in nested_list for e in inner_list]

def do_it():
    """ APIを叩いて接続を確立 """
    amazon = api.Amazon(AMAZON_ACCESS_KEY_ID, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, Region="JP",
        Parser=lambda text: BeautifulSoup(text), ErrorHandler=error_handler
    )

    """ クエリを投げるやつ """
    """ おすすめ順 """
    item_list = flatten([item_search(x, amazon) for x in range(1,11)])

    """ 売れ筋ランキング """
#    item_list = browse_node_lookup(amazon)

    """ 新着ランキング """
#    item_list = new_release_lookup(amazon)

    """ 出力する """
    rank = 1
    for item in item_list:
        print rank,item.title.string.encode('utf-8'),item.author.string.encode('utf-8'),item.asin.string.encode('utf-8')
        rank = rank + 1
    """ CSVに出力する予定の項目(PythonのDB操作はまだ知らない) """
    """ StartTime, EndTime, BookName, Author, ASIN, Rank / 2h """

if __name__ == '__main__':
    do_it()


んで、出力の一部は以下。

1 殺戮にいたる病 (講談社文庫) 我孫子武丸 B00FOKKQ5A
2 有頂天家族 (幻冬舎文庫) 森見登美彦 B009CTUN8O
3 夜は短し歩けよ乙女 (角川文庫) 森見 登美彦 B0093GEBJS
4 夏への扉 ロバート A ハインライン B00CZ840H4
5 新世界より(上) (講談社文庫) 貴志祐介 B009GXME5G
6 虐殺器官 (ハヤカワ文庫JA) 伊藤 計劃 B009DEMA02
7 新世界より(下) (講談社文庫) 貴志祐介 B009GXMFU0
8 新世界より(中) (講談社文庫) 貴志祐介 B009GXMEV0
9 know 野崎まど B00FJ1DWH8
10 黒い家 (角川ホラー文庫) 貴志 祐介 B009GPM5GM
11 天使の囀り (角川ホラー文庫) 貴志 祐介 B00AIITE74
12 獣の奏者 III探求編 (講談社文庫) 上橋菜穂子 B00AJCM5BG
13 獣の奏者 II王獣編 (講談社文庫) 上橋菜穂子 B00AJCM5AM
14 獣の奏者 I闘蛇編 (講談社文庫) 上橋菜穂子 B00AJCM55W

15 遊星ジャーナル『大いに偉大なる重力の遊星』 (青聿書房) 片倉青一 B072MQ9RLW

16 時砂の王 小川一水 B00GJMUKQW
17 獣の奏者 外伝 刹那 (講談社文庫) 上橋菜穂子 B00GD6ER4A
18 獣の奏者 IV完結編 (講談社文庫) 上橋菜穂子 B00AJCM5IY
19 タイタンの妖女 カート ヴォネガット ジュニア B00C2R9UUK
20 毒見師イレーナ (ハーパーBOOKS) マリア・V スナイダー B0107Q8R9C

すげえな遊星ジャーナル

じゃなくて。

色々と困ったことが分かりました。

Kindle本のカテゴリランキングにも色々ありまして
おすすめ順(上記で取得したのはこれです)
売れ筋ランキング(個別の書籍ページに表示されるランキングです)
新着ランキング

なんと
おすすめ順と売れ筋ランキングで順位が異なる
という問題があります。

おすすめ順(2017年6月18日11時時点)
f:id:KtkrAo1:20170618115931p:plain

売れ筋ランキング(2017年6月18日11時時点)
f:id:KtkrAo1:20170618115921p:plain

個別の書籍ページに表示されるのは売れ筋ランキングですので、このランキングを1位から100位まで取りたいところなのですが、残念ながら売れ筋ランキングについてはトップ10までしか取得できないようです。

元々やりたかったことはランキングの推移をデータとして蓄積することです。
Amazonのランキングは1時間ごとに変動します。
現状、売れ筋ランキングはトップ10までしか取れませんので、
スクリプトを置くサーバの都合上)2時間に一回ほどAPIを叩いて結果をCSVに保存する、という要件を満たせません。

書籍を指定してそいつだけのランキングを取ってくることもできるのですが、そうすると他との比較ができません。
データを取りたい最大の理由が、最終的に蓄積したデータをポートフォリオにするということです。
要するにデータ片手に出版社に売り込むなり、グラフ化して販促するなりしたいということです。


どうしようかなあ。

©青聿書房 Aofude Shobo