09f5d33684d1cf48da1732aa6f984823

はじめに

2016年の8月からamazonではkindle unlimited(読み放題)のサービスが始まりました。
自分が契約したのはつい先日で、コンピュータの書籍が意外にたくさんあったの契約することに決めました。

契約して実際に使ってみると、こういうのところが使いにくいとか、こういう本が少ないとか・・・思うところ事がありました。
一番気になったのが新刊が探しにくいというところでしょうか。
膨大な数の本が常に増えており、新しい本が追加されても気づかないという点です。
amazonサイトでは新刊による絞込はあるのですが、これは発売日での絞り込みであり、kindle unlimitedの本が新刊として追加されたこという事には必ずしもなりません。
例として、1年以上前に発売された本が新しくkindle unlimitedに追加場合、kindle unlimitedには新しく追加されているのですが、発売日が1年以上前のため、サイトの新刊絞込には出てこない(おそらく)という事です。
これではkindle unlimitedで新しく追加された本が探せないですよね。
いつの間にか素敵なタイトルが追加されているかもしれません。

では、どうしたら探せるでしょうか。。。

うーん。妙案が思いつかなかったので、とりあえず全マスタデータを取得すれば追加された本が特定できると考えました。

方法

まず取得する対象データですが、kindle unlimiteでは和書12万冊以上、洋書120万冊以上の本の数を誇ります。
さすがに洋書まで全件取得するのは骨が折れますので、今回は和書12万冊をターゲットにします。

amazonから商品マスタデータを取得する方法としては、Product Advertising APIを使う方法があります。
スクレイピングで出来ないことはないですが、amazonの利用規約に反するので、APIを使ってアクセスすることとします。

Product Advertising APIは事前にamazonアソシエイトの登録と、APIの利用申請が必要となります。
公式サービスのため、マニュアルを参考に利用登録をします。

具体的に利用するAPIは2つ。

  • BrowseNodeLookup。ノードの関連情報を取得するAPI
  • ItemSearch。アイテム情報を検索するAPI

まずは、BrowseNodeLookupを使ってKindle Unlimited:読み放題 ジャンル(3197885051)に属している子のnode(カテゴリ)の情報を取得します。例)Kindle Unlimited:読み放題 ジャンル> コミック 等
次に取得したnodeに属している本をItemSearchを使って取得していきます。
次に取得した情報をDBに格納します。DBは何でもいいですが今回はmysqlを使いました。
最後に取得したデータで前回データ取得時になかったものを新規登録することで、新しく追加されたデータの特定を行います。

考慮のポイント(メモ)

使うプログラム言語・ツール

プログラムはこちらの記事に載せてます。

・接続クライアント
APIを使うのでプログラムが必要になります。
言語はrubyか迷いましたが、今回はライブラリが豊富なpythonにしました。
ライブラリはbottlenoseを使用します。
このライブラリを使えばamazonへの接続部分は自分でコードを書かなくて済みます。
APIのレスポンスはXMLなので、BeautifulSoupを使って一発で情報を取れます。(さすがpython)

インストールコマンド
$ pip install bottlenose
$ pip install beautifulsoup4

・mysqlへの接続
python3に対応したmysqlclientを使用。

インストールコマンド
$ pip install mysqlclient

ItemSearchページ上限の回避

Product Advertising APIを使っていると必ず行き着く問題として、取得できるページ数に上限(10ページ)があるという事です。
1ページ10件なので、100件のデータしか取得できない事になります。特に「文芸・評論」と「コミック」はデータ件数が多いので、この課題に対応する方法があります。
具体的な方法としては、ItemSearchの検索条件を増やして一回に取得できる件数を10ページ以下に抑えていきます。
検索条件として使ったのは、価格上限・下限、発行年月、タイトル、出版社、著者などです。
処理がごちゃごちゃしたプログラムになりますが、この辺りのパラメータを組み合わせて取得することで一部を除き(※1)何とか10ページ以下に抑えることが出来ます。
使い方は公式マニュアル公式デモが分かりやすいです。

※1 同じシリーズの本で、同じタイトル、同じ値段、同じ発行年月のものがあります。
今回取得できなかったのが「誕生日占い YOUR BIRTHDAY X月XX日」と「365誕生星占い~X月XX日生まれのあなたへ~」シリーズの2つです。
なんと誕生日分の冊数があるという驚愕のシリーズで、どうしても1回の検索結果を10ページ以下に抑えることができません。
強引にタイトルを解析すれば全部取得できないことはないですが、この2つのシリーズのためにコードを書く(労力を費やす)のは微妙なので、今回はスルーすることにしました。

サブカテゴリに属していないマスタ多数

Kindle Unlimitedのカテゴリとしては、文学・評論、人文・思想、社会・政治、コミック・・・等があります。(以下メインカテゴリとします。)
さらにそのサブカテゴリとしては、コミック->少年コミック、コミック->少女コミック等があります。

そこで気づいたのがサブカテゴリの件数の合計=メインカテゴリの件数とはならないことです。

例としてコミックですが、メインカテゴリの件数は29,204件となっているのですが、サブカテゴリの合計が3,500件程度にしかなりません。%e7%84%a1%e9%a1%8c

これは、kindleのサブカテゴリに属していないデータがたくさんあるという事です。
なので、サブカテゴリの単位で集計をすると、取得できないデータが出てくるので、サブカテゴリを使いつつ、メインカテゴリでの情報取得も必要になります。

通信間隔とHTTPエラー

Product Advertising APIのリクエスト制限として、1時間に3600回以下とされています。
アフィリエイト経由の売上げが上がると、上限数が上がるみたいですが現実的ではないので、上限を超えない程度に制限をします。

1時間に3600回なので1秒に1回の通信にすることで、ちょうど1時間で3600回程度の通信になります。
適度にプログラムにsleepを入れてコントロールします。

たいてい、問題なく処理はできるのですが定期的にamazonのサーバよりHTTP 503エラーが返されます。
ここは少し間を空けてからリトライすることで回避をしました。

取得にかかる時間

1時間に3600リクエストが上限となり、最大1時間に36000件なので12万のデータを4時間程度で取得できる計算になりますが、実際には7時間~8時間は取得にかかります。
理由として一つ目は、リクエストを投げてみないとデータがあるか分からないところもあり、無駄なリクエストを投げることが多いという点です。(プログラムの組み方次第だとは思いますが・・・)
二つ目は複数のカテゴリに属しているデータが多く、それぞれのカテゴリで複数回取得しているということです。
特にコミックとアダルトで重複しているデータが多いと思います。

この二つはなかなか回避できないと思いますので、少しでも時間を短縮する方法としては、amazonアソシエイトのアカウントを複数使うというぐらいでしょうか。
試してませんが、複数アカウントで分散してデータを取得しにいけば1時間でたくさんのデータが取得できますので、時間は短縮されるはずです。

参考文献、利用サイト

まとめ

結果として、データを取得するには結構な考慮が必要でした。
とは言え何とかおおよそ全件のデータを取得できましたので、次回は一般の方でも新刊が探せるようなWEBサービスを作って見たいと思います。