<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Amazon Product Advertising API - イチゾーのブログ</title>
	<atom:link href="https://ichizo.biz/tag/amazon-product-advertising-api/feed" rel="self" type="application/rss+xml" />
	<link>https://ichizo.biz</link>
	<description>システム開発やWordPressについてなど</description>
	<lastBuildDate>Mon, 20 Mar 2017 15:32:48 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>
<site xmlns="com-wordpress:feed-additions:1">120380898</site>	<item>
		<title>Kindle Unlimitedの対象本を検索できるページをPHPで作ってみた</title>
		<link>https://ichizo.biz/2017/03/21/kindle-unlimited-php.html</link>
					<comments>https://ichizo.biz/2017/03/21/kindle-unlimited-php.html?noamp=mobile#comments</comments>
		
		<dc:creator><![CDATA[一蔵]]></dc:creator>
		<pubDate>Mon, 20 Mar 2017 15:32:48 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Amazon Product Advertising API]]></category>
		<category><![CDATA[Kindle Unlimited]]></category>
		<guid isPermaLink="false">http://ichizo.biz/?p=226</guid>

					<description><![CDATA[<p>Kindle Unlimitedの対象本を検索できるページを [&#8230;]</p>
<p>The post <a href="https://ichizo.biz/2017/03/21/kindle-unlimited-php.html">Kindle Unlimitedの対象本を検索できるページをPHPで作ってみた</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2>Kindle Unlimitedの対象本を検索できるページをPHPで作ってみた</h2>
<p>Kindle Unlimitedを契約して使っていますが、<br />
いまいち検索が使いずらいのが玉にキズです。</p>
<p>Amazonで「Kindle本」のカテゴリページを開くと<br />
Kindle Unlimited対象本の一覧を見ることはできます。</p>
<p>ただ、対象件数が非常に多いので、<br />
１ページずつ見ていくのは現実的ではありません。</p>
<p>洋書（英語の本）も多いので、<br />
英語多読用にKindle Unlimitedで良い本を探したいと<br />
思っているのですが、ペンギンリーダーズやラダーシリーズなど<br />
多読用に向いている本は意外にKindle Unlimitedで<br />
対象になっていなかったりします。</p>
<p>英語多読に使いたい本は、絵本などの簡単な英語の本なのですが、<br />
そういう本でKindle Unlimitedの対象本から探すのが<br />
結構めんどくさかったりします。</p>
<p>ペンギンリーダーズやラダーシリーズがいいと思って<br />
Kindle本カテゴリで検索してみますが、<br />
Kindleでは読めますが、読み放題にはなっていません。</p>
<p>Kindle Unlimiteの対象本を探したいということで<br />
「Kindle Unlimited」をキーワードに検索しても、<br />
「Kindle Unlimited」についての解説をしている本<br />
（タイトルに「Kindle Unlimited」が入っているような本）<br />
しか検索リストに出てきません。</p>
<p>カテゴリを「Kindle Unlimited」のみに絞って<br />
その中から入力したキーワードにマッチした<br />
検索を行いたいのですが、Amazonページ上では<br />
なかなかそれができません。</p>
<p>できないならAmazon Product Advertising APIを<br />
使って検索ページを作ってしまえということで、<br />
ちゃちゃっと作ってみました。</p>
<p>とりあえず、キーワードを入力して<br />
Kindle Unlimitedで一致する結果を<br />
一覧で表示させるという簡便な検索システムを<br />
実装してみました。</p>
<h3>サイトデザインどうしよう？</h3>
<p>とりあえずで作るサイトですが、<br />
あまりにもダサいデザインにはしたくない、<br />
とはいってもデザイナーではないので<br />
自分でちゃちゃっとWEBデザインが<br />
出来るわけではありません。</p>
<p>手軽にできてそれなりの見た目にしたいということで、<br />
Bootstrapを利用しようと思いつきます。</p>
<p>Bootstrapもテーマを利用すると<br />
より手軽に使えるだろうと<br />
Bootstrapテーマを探してみました。</p>
<p>日本語も美しく表示できるという<br />
<a href="http://honokak.osaka/" target="_blank">Honoka</a><br />
というBootstrapテーマがよさそうなので<br />
これを使ってみることにしました。</p>
<h3>プログラムの実装</h3>
<p>最初に<a href="http://honokak.osaka/" target="_blank">Honoka</a>をダウンロードします。</p>
<p>ダウンロードしたファイルを解凍すると、<br />
「honoka」フォルダができるので、<br />
このhonokaフォルダ上に以下の<br />
index.phpとrequest.phpを作ります。</p>
<h4>index.php</h4>
<p>画面表示用のPHPファイルです。</p>
<pre class="lang:php decode:true " title="index.php" >
&lt;?php
if (!empty($_POST['keyword'])) {
    include_once('request.php');
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang="ja"&gt;
&lt;head&gt;
&lt;meta charset="utf-8"&gt;
&lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
&lt;!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --&gt;
&lt;title&gt;Kindle Unlimited検索ページ&lt;/title&gt;

&lt;!-- Bootstrap --&gt;
&lt;link href="css/bootstrap.min.css" rel="stylesheet"&gt;
  &lt;style type="text/css"&gt;
  .col-lg-4 {
    width: 100%;
  }
  .list-group-item-image {
    float: left;
    padding-right: 10px;
  }
  .list-group-item-image img {
    height: 200px;
  }
  @media ( min-width: 568px ) {
  }
  &lt;/style&gt;


&lt;!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --&gt;
&lt;!-- WARNING: Respond.js doesn't work if you view the page via file:// --&gt;
&lt;!--[if lt IE 9]&gt;
&lt;script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"&gt;&lt;/script&gt;
&lt;script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"&gt;&lt;/script&gt;
&lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="container"&gt;
  &lt;div class="bs-docs-section clearfix"&gt;

    &lt;div class="row"&gt;
      &lt;div class="col-lg-12"&gt;
        &lt;div class="page-header"&gt;
          &lt;h1 id="navbar"&gt;Kindle Unlimited検索&lt;/h1&gt;
        &lt;/div&gt;

        &lt;div class="bs-component"&gt;
          &lt;nav class="navbar navbar-default"&gt;
            &lt;div class="container-fluid"&gt;

              &lt;div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"&gt;
                &lt;form class="navbar-form navbar-left" role="search" action="index.php" method="POST"&gt;
                  &lt;div class="form-group"&gt;
                    &lt;input type="text" class="form-control" placeholder="Search" name="keyword"&gt;
                  &lt;/div&gt;
                  &lt;button type="submit" class="btn btn-default"&gt;検索&lt;/button&gt;
                &lt;/form&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/nav&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

&lt;?php
if (!empty($_POST['keyword'])) {
?&gt;
    &lt;div class="row"&gt;
      &lt;div class="col-lg-12"&gt;
        &lt;h2&gt;検索結果&lt;/h2&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
      &lt;div class="col-lg-4"&gt;
        &lt;div class="bs-component"&gt;
          &lt;div class="list-group"&gt;
&lt;?php
    foreach ($item_tags as $item) {
        echo $item;
    }
?&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;?php
}
?&gt;
  &lt;/div&gt;
&lt;/div&gt;

    &lt;!-- jQuery (necessary for Bootstrap's JavaScript plugins) --&gt;
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;!-- Include all compiled plugins (below), or include individual files as needed --&gt;
    &lt;script src="js/bootstrap.min.js"&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>検索を行うと、自分自身にPOSTでキーワードを投げます。<br />
POSTがあると、request.phpを呼び出し、<br />
検索結果を表示するとしています。</p>
<h4>request.php</h4>
<p>続いてはrequest.phpです。<br />
このファイルでは、入力したキーワードに対して<br />
Amazon Product Advertising APIを実行し、<br />
検索結果を一覧に表示します。</p>
<pre class="lang:php decode:true " title="request.php" >
&lt;?php
define("BaseUrl", "https://webservices.amazon.co.jp/onca/xml");

// Amazon APIのアクセスキーとシークレットキーを入力
define("Access_Key_ID", "アクセスキー");
define("Secret_Access_Key", "シークレットアクセスキー");
// アソシエイトIDの入力
define("Associate_tag", "アソシエイトID");

define("KINDLE_UMLIMITED_BROWSE_NODE_ID", "4486610051");

// リクエストのパラメータ作成
$params = array();
$params["Service"]          = "AWSECommerceService";
$params["AWSAccessKeyId"]   = Access_Key_ID;
$params["Version"]          = "2013-08-01";
$params["Operation"]        = "ItemSearch";
$params["SearchIndex"]      = "KindleStore";
$params["Keywords"]         = $_POST['keyword'];
$params["AssociateTag"]     = Associate_tag;
$params["ResponseGroup"]    = "ItemAttributes,Offers, Images";
$params["MinimumPrice"]     = "100";
$params["ItemPage"]         = "1";
$params["BrowseNode"]         = KINDLE_UMLIMITED_BROWSE_NODE_ID;


$base_request = "";
foreach ($params as $k =&gt; $v) { $base_request .= "&amp;" . $k . "=" . $v; }
$base_request = BaseUrl . "?" . substr($base_request, 1);

$params["Timestamp"] = gmdate("Y-m-d\TH:i:s\Z");
$base_request .= "&amp;Timestamp=" . $params['Timestamp'];

$base_request = "";
foreach ($params as $k =&gt; $v) {
	$base_request .= '&amp;' . $k . '=' . rawurlencode($v);
	$params[$k] = rawurlencode($v);
}
$base_request = BaseUrl . "?" . substr($base_request, 1);

$base_request = preg_replace("/.*\?/", "", $base_request);
$base_request = str_replace("&amp;", "\n", $base_request);

ksort($params);
$base_request = "";
foreach ($params as $k =&gt; $v) { $base_request .= "&amp;" . $k . "=" . $v; }
$base_request = substr($base_request, 1);
$base_request = str_replace("&amp;", "\n", $base_request);

$base_request = str_replace("\n", "&amp;", $base_request);

$parsed_url = parse_url(BaseUrl);
$base_request = "GET\n" . $parsed_url['host'] . "\n" . $parsed_url['path'] . "\n" . $base_request;

$signature = base64_encode(hash_hmac('sha256', $base_request, Secret_Access_Key, true));
$signature = rawurlencode($signature);

$base_request = "";
foreach ($params as $k =&gt; $v) { $base_request .= "&amp;" . $k . "=" . $v; }
$base_request = BaseUrl . "?" . substr($base_request, 1) . "&amp;Signature=" . $signature;

$item_tags = ItemSearch($base_request);

function ItemSearch($base_request) {
    $amazon_xml = simplexml_load_string(file_get_contents($base_request));
    $item_tags = array();
    
	foreach($amazon_xml-&gt;Items-&gt;Item as $item) {
		$item_title = $item-&gt;ItemAttributes-&gt;Title; // 商品名
		$item_author = $item-&gt;ItemAttributes-&gt;Author; // 著者
		$item_publicationdate = $item-&gt;ItemAttributes-&gt;PublicationDate; // 発売日
		$item_publisher = $item-&gt;ItemAttributes-&gt;Publisher; // 出版社
		$item_url = $item-&gt;DetailPageURL; // 商品のURL
		$item_image	 = $item-&gt;LargeImage-&gt;URL; // 商品の画像
		
		$item_tags[] = '            &lt;a class="list-group-item clearfix" href="'.$item_url.'" target="_blank"&gt;
                &lt;div class="list-group-item-image"&gt;
                    &lt;img src="'.$item_image.'" /&gt;
                &lt;/div&gt;
                &lt;p class="list-group-item-title"&gt;
                    '.$item_title.'
                &lt;/p&gt;
            &lt;/a&gt;';
	}
	return $item_tags;
}
</pre>
<p>request.phpはGithubの<br />
<a href="https://github.com/manabubannai/amazon-api-test-blog" target="_blank">manabubannai/amazon-api-test-blog</a>を参考にさせていただきました。</p>
<h3>サーバーにアップして公開</h3>
<p>index.phpとrequest.phpができたら<br />
honokaフォルダごとサーバーにアップします。</p>
<p>試しに作ってみたサイトがこれです。<br />
<a href="http://kindle.ichizo.biz/" target="_blank">Kindle Unlimited検索</a></p>
<p>とりあえず作ったサイトは味も素っ気もありませんが、<br />
ここから英語多読用に使えそうな本など<br />
ピックアップできればと考えています。</p><p>The post <a href="https://ichizo.biz/2017/03/21/kindle-unlimited-php.html">Kindle Unlimitedの対象本を検索できるページをPHPで作ってみた</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://ichizo.biz/2017/03/21/kindle-unlimited-php.html/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">226</post-id>	</item>
		<item>
		<title>PythonでAmazon Product Advertising APIを呼び出してKindle Unlimitedの情報を取得する</title>
		<link>https://ichizo.biz/2016/12/29/kindle-unlimited.html</link>
					<comments>https://ichizo.biz/2016/12/29/kindle-unlimited.html?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[一蔵]]></dc:creator>
		<pubDate>Thu, 29 Dec 2016 08:25:19 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[英語]]></category>
		<category><![CDATA[Amazon Product Advertising API]]></category>
		<category><![CDATA[英語多読]]></category>
		<guid isPermaLink="false">http://ichizo.biz/?p=100</guid>

					<description><![CDATA[<p>「英語多読用の本をレベル別に取得する（完成版）」で、 英語多 [&#8230;]</p>
<p>The post <a href="https://ichizo.biz/2016/12/29/kindle-unlimited.html">PythonでAmazon Product Advertising APIを呼び出してKindle Unlimitedの情報を取得する</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>「<a href="http://ichizo.biz/2016/12/29/python-selenium-3.html">英語多読用の本をレベル別に取得する（完成版）</a>」で、<br />
英語多読用の本のISBNリストを取得しました。</p>
<p>今度はこれを使用して、Amazon Product Advertising APIを呼び出してKindle Unlimitedの情報を取得するということをやります。</p>
<h2>目的：英語多読をKindle Unlimitedでやりたい</h2>
<p>英語力を伸ばしたいということで、英語多読をやってみたいのですが、<br />
多読用の本を買っていては高くついてしまうというネックがあります。</p>
<p><a href="https://www.seg.co.jp/sss/learning/sss-for-low-intermeidate.html" target="_blank">英語多読研究会さんのHP</a>に、難易度別の類型読書語数の目安が掲載されています。</p>
<p>それによると、各レベルごとの累計語数は以下のようになっています。</p>
<pre>
Level0　　 30,000語
Level1　　120,000語
Level2　　470,000語
Level3　1,020,000語
Level4　1,320,000語
Level5　1,600,000語
Level6　1,900,000語
Level7　2,000,000語
Level8　2,200,000語
Level9　2,380,000語
</pre>
<p>これを達成するためには、各レベルで以下の冊数が必要になります。</p>
<pre>
Level0　30冊
Level1　30冊
Level2　50冊
Level3　50冊
Level4　15冊
Level5　10冊
Level6　10冊
Level7　2冊
Level8　2冊
Level9　1冊
</pre>
<p>Level0では、3万語の読書語数が推奨されていますが、<br />
これを満たすためには大体30冊読まなければいけないという計算になります。</p>
<p>Level9では、読書語数は18万語となっていますが、<br />
読むべき冊数は1冊です。</p>
<p>これは、難易度があがると1冊あたりの語数が増えるため、<br />
読む必要がある冊数は減ってくるということですね。</p>
<p>英語多読を始めたばかりの難易度の低い頃に読むのが<br />
語数が少なく読みやすい本（児童向けだったりします）になりますので、<br />
必然的に読むべき冊数が増えてしまいます。</p>
<p>１冊あたり500円とか600円とかなので、決して高いわけではありませんが、<br />
Level0で30冊、Level1で30冊、Level2で50冊・・・<br />
となると、一人で揃えるには予算的に非常に厳しいものがあります。</p>
<p>そこで、読み放題のKindle Unlimitedを英語多読に使えないかと考えた訳です。</p>
<p>英語多読研究会さんでは、<a href="http://www.seg.co.jp/sss_review/jsp/frm_a_100.jsp" target="_blank">多読用の洋書のリストを難易度別に公開されています</a>ので、<br />
ここで公開されている本のリストから、Kindle Unlimitedに登録されているものを探し出すということをやってみます。</p>
<p>多読用の本のリスト取得は<a href="http://ichizo.biz/2016/12/29/python-selenium-3.html">前回</a>までに行っていますので、<br />
今回は取得したリストを元にAmazon Product Advertising APIを呼び出して本の情報を取得するということをやってみます。</p>
<p>ソースコード</p>
<pre class="lang:python decode:true " title="amazon_api.py" >
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 19 14:49:19 2016

@author: 
"""

from bottlenose import api
from lxml import objectify
import time

AMAZON_ACCESS_KEY_ID = "アクセスキー"
AMAZON_SECRET_KEY = "シークレットキー"
AMAZON_ASSOC_TAG = "アソシエイトタグ"

KINDLE_UMLIMITED_NODE_ID = "4486610051"

amazon = api.Amazon(AMAZON_ACCESS_KEY_ID, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, Region = "JP")

def file_read (file):
    f = open(file, 'r')
    data = f.read()
    f.close()
    lines = data.split('\n')
    return lines

def loop_min(max_level):
    book_list = []
    min_level = 0
    while min_level &lt; 1:
        level = max_level + min_level
        print('list'+str('%1.1f' % level)+'.txt')
        lines = file_read('list'+str('%1.1f' % level)+'.txt')
        for line in lines:
            if (len(line) &gt; 0):
                print('line='+line)
                items = item_search(line)
                item_find = items.find('Item')
                if (item_find is not None):
                    for item in item_find:
                        if (item is not None):
                            title = item.ItemAttributes.Title
                            author = item.ItemAttributes.Author
                            isbn = item.ItemAttributes.Isbn
                            url = item.DetailPageURL
                            print(("%s, %s, %s, %s, %s" % (line, title, author, isbn, url)))
                            book_list.append(str("%s, %s, %s, %s, %s" % (line, title, author, isbn, url)))
                        else:
                            print ("%s : Book is None" % (line))
                #print ("END %s" % (line))
                time.sleep(5)   # Amazon API呼び出しは1秒に1回以内に収めるためsleep

        min_level += 0.1
        
    return book_list
    
def loop_max():
    max_level = 0
    while max_level &lt; 10:
        book_list = loop_min(max_level)
        write_file(book_list, max_level)
        max_level += 1
    
def write_file(book_list, max_level):
    f = open('amazon'+str('%1d' % max_level)+'.txt', 'w')
    for book in book_list:
        f.write(book)
        f.write('\n')
    f.close()

def item_search (keywords, searchIndex="KindleStore", browseNode=KINDLE_UMLIMITED_NODE_ID):
    response = amazon.ItemSearch(Keywords=keywords, SearchIndex=searchIndex, BrowseNode=browseNode, ResponseGroup="Large")
    root = objectify.fromstring(response)
    return root.Items

if __name__ == '__main__':
    
        loop_max()
</pre>
<p>bottlenoseを使ってAmazon Product Advertising APIを呼び出しています。</p>
<p>この使い方は<a href="http://ichizo.biz/2016/12/20/english-kindle-unlimited.html">以前の記事</a>を参考にしてください。</p>
<p>今回やっていることは、ISBNのリストファイルを開き１行ずつAmazon Product Advertising APIで<br />
Kindle Unlimitedの情報を取得するということです。</p>
<p>ループの頻度ですが、Amazon Product Advertising APIには<br />
頻繁にアクセスするとエラーを返す仕様がある（1秒間に1回以内に抑える）ので<br />
sleepを5秒入れています。</p>
<p>これで実行していたのですが、<br />
「接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。」<br />
というエラーが返ってきて中断しましたので、sleep 10秒で再トライしてみます。</p>
<p>英語多読で使えるKindle Unlimitedの本のリストはまとめて公開したいと思います。</p><p>The post <a href="https://ichizo.biz/2016/12/29/kindle-unlimited.html">PythonでAmazon Product Advertising APIを呼び出してKindle Unlimitedの情報を取得する</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://ichizo.biz/2016/12/29/kindle-unlimited.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">100</post-id>	</item>
		<item>
		<title>英語多読用リストがKindle Unlimitedに存在するか自動チェックしてみる</title>
		<link>https://ichizo.biz/2016/12/20/english-kindle-unlimited.html</link>
					<comments>https://ichizo.biz/2016/12/20/english-kindle-unlimited.html?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[一蔵]]></dc:creator>
		<pubDate>Tue, 20 Dec 2016 08:50:13 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[英語]]></category>
		<category><![CDATA[Amazon Product Advertising API]]></category>
		<category><![CDATA[bottlenose]]></category>
		<category><![CDATA[Kindle Unlimited]]></category>
		<guid isPermaLink="false">http://ichizo.biz/?p=73</guid>

					<description><![CDATA[<p>PythonでAmazonのKindle Unlimited [&#8230;]</p>
<p>The post <a href="https://ichizo.biz/2016/12/20/english-kindle-unlimited.html">英語多読用リストがKindle Unlimitedに存在するか自動チェックしてみる</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><a href="http://ichizo.biz/2016/12/20/python-kindleunlimited.html">PythonでAmazonのKindle Unlimited情報を取得してみる</a>に続いて、<br />
あらかじめテキストファイルに記載していた書名を取得して<br />
Amazon Product Advertising APIに対して検索を行います。</p>
<h2>Pythonでテキストファイルを開く</h2>
<p>テキストファイルは、以下のようなソースで読み込みます。</p>
<pre class="lang:python decode:true " >
#!/usr/bin/env python

f = open('text.txt', 'r')

for line in f:
    print line
    
f.close()
</pre>
<p>読み込みたいのは以下のようなテキストファイルです。</p>
<pre class="lang:default decode:true " >
Foundations Reading Library
Penguin Readers Easystarts
Oxford Bookworms Starters
Macmillan Readers Starter
Macmillan New Wave Readers Level 1
Oxford Reading Tree
Longman Literacy Land Story Street
Macmillan Springboard
Rookie Readers Fiction
Cambridge Storybooks
Longman Shared Reading
Oxford Start with English Readers
Longman Big and Little Books
CTP Emergent Readers
100 English
Sight Word Readers
Time-to-Discover Readers
Step into Reading Step 1
Step into Reading Step 2
Scholastic Reader Level1
Scholastic Reader Level2
My First I Can Read Books
I Can Read Books Level 1
Penguin Young Readers Level 1
Ready-to-Read Pre-Level 1
Ready-to-Read Level 1
Ready-to-Read Level 2
All Aboard Reading Picture Books
All Aboard Reading Level 1
Puffin Easy-to-Read Level 1
Addison Wesley Big and Little Books
Oxford Classic Tales
Curious George Short Stories
Dorling Kindersley Readers Level 1
Dorling Kindersley Readers Level 2
Oxford Dominoes Stage 0
Penguin Young Readers Level 2
Longman Chatterbox
TL PM Readers
HM Leveled Reading Grade 1
The Very Hungry Caterpillar
Good Night Moon
Brown Bear, Brown Bear, What Do You See?
</pre>
<h3>英語多読用の本のリストが欲しい</h3>
<p>これは何かというと、英語多読用の本のリストです。</p>
<p>SSS英語多読研究会がすすめる「<a href="https://www.seg.co.jp/sss/learning/" target="_blank">非常にやさしい本からはじめ、１００万語単位で読む多読</a>」をやってみたいと思っていたのですが、<br />
多読をするためにはまず教材となる英語の本を用意する必要があります。</p>
<p>SSS英語多読研究会では、<a href="https://www.seg.co.jp/sss/review/osusume.html" target="_blank">レベル別に読むべき本を紹介してくれています</a>。</p>
<p>問題は、多読をするためには大量の本を読まなければいけないのですが、<br />
目安である100万語まで到達するまでにはかなりの本が必要になります。</p>
<p>特にレベルの低いころに読む本は、1冊あたりの字数が少ないために<br />
どうしても本の数が多くなってしまいます。</p>
<p>１冊500円～600円程度で購入できるので、数冊買う分にはいいのですが、<br />
多読となると数十冊単位で読む必要があります。<br />
となると、数万円は軽くかかります。</p>
<p>しかもそのレベルを通り過ぎてしまえば、必要がなくなってしまうという<br />
悲しい運命が待っています。<br />
簡単なものから始めるがゆえに、ほぼ読み捨てしなければならないということです。</p>
<p>そこで目を付けたのが、Kindle Unlimitedです。</p>
<p>読み放題のKindle Unlimitedであれば、お金を気にせず読み進められます。<br />
洋書もかなりの冊数あります（先ほど洋書一覧で見ると137万冊以上あるようです）ので、<br />
きっと多読に使える本もあるはずということです。</p>
<p>ただ、ここで問題になるのは対象になる本を見つける方法です。<br />
リストにあがっている本をいちいち検索するのはメンドくさい、<br />
そもそもKindle Unlimitedにない本もある（ないことが多い）、<br />
効率よく多読するには本を効率よく見つけることも大切だということで<br />
リストからKindle Unlimitedにあるのかを探すプログラムを作ることにしました。</p>
<p>今回検索するリストは、SSS英語多読研究会がレベル0として推薦しているものです。</p>
<h3>書名リストからAmazon Product Advertising APIを呼び出すプログラム</h3>
<p>書名リストのテキストをlevel0.txtとして、Pythonプログラムと同じディレクトリに置きます。</p>
<p>前回の「<a href="http://ichizo.biz/2016/12/20/python-kindleunlimited.html">PythonでAmazonのKindle Unlimited情報を取得してみる</a>」に、ファイルの読み込み処理を組み込みます。</p>
<p>修正したプログラムが以下です。</p>
<pre class="lang:python decode:true " >
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 19 14:49:19 2016

@author: 
"""

from bottlenose import api
from lxml import objectify
import time

AMAZON_ACCESS_KEY_ID = "アクセスキー"
AMAZON_SECRET_KEY = "シークレットキー"
AMAZON_ASSOC_TAG = "アソシエイトタグ"

KINDLE_UMLIMITED_NODE_ID = "4486610051"

amazon = api.Amazon(AMAZON_ACCESS_KEY_ID, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, Region = "JP")

def file_read (file):
    f = open(file, 'r')
    data = f.read()
    f.close()
    lines = data.split('\n')
    return lines

def item_search (keywords, searchIndex="KindleStore", browseNode=KINDLE_UMLIMITED_NODE_ID):
    response = amazon.ItemSearch(Keywords=keywords, SearchIndex=searchIndex, BrowseNode=browseNode, ResponseGroup="Large")
    root = objectify.fromstring(response)
    return root.Items.Item

if __name__ == '__main__':

    lines = file_read('level0.txt')
    for line in lines:
        for item in item_search(line):
            title = item.ItemAttributes.Title
            author = item.ItemAttributes.Author
            url = item.DetailPageURL
            print ("%s\n%s\n%s\n%s\n\n" % (line, title, author, url))
        time.sleep(5)   # Amazon API呼び出しは1秒に1回以内に収めるためsleep
</pre>
<p>file_readというメソッドを作って、ここでテキストファイルを読み込み<br />
１行ずつを配列の各要素に入れて返します。</p>
<p>file_readの呼び出し元では、返り値でループさせます。<br />
その際に、sleep(5)を入れています。</p>
<p>これで実行してみると、<br />
「AttributeError: no such child: {http://webservices.amazon.com/AWSECommerceService/2013-08-01}Item」<br />
というエラーで終了します。</p>
<p>APIの結果がない場合にエラーで落ちてしまっています。<br />
今度はこれの対策を考えます。</p>
<p>以下のように書き換えてみました。</p>
<pre class="lang:python decode:true " >
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 19 14:49:19 2016

@author: 
"""

from bottlenose import api
from lxml import objectify
import time

AMAZON_ACCESS_KEY_ID = "アクセスキー"
AMAZON_SECRET_KEY = "シークレットキー"
AMAZON_ASSOC_TAG = "アソシエイトタグ"

KINDLE_UMLIMITED_NODE_ID = "4486610051"

amazon = api.Amazon(AMAZON_ACCESS_KEY_ID, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, Region = "JP")

def file_read (file):
    f = open(file, 'r')
    data = f.read()
    f.close()
    lines = data.split('\n')
    return lines

def item_search (keywords, searchIndex="KindleStore", browseNode=KINDLE_UMLIMITED_NODE_ID):
    response = amazon.ItemSearch(Keywords=keywords, SearchIndex=searchIndex, BrowseNode=browseNode, ResponseGroup="Large")
    root = objectify.fromstring(response)
    return root.Items

if __name__ == '__main__':

    lines = file_read('level0.txt')
    for line in lines:
        items = item_search(line)
        item_find = items.find('Item')
        if (item_find is not None):
            for item in item_find:
                if (item is not None):
                    title = item.ItemAttributes.Title
                    author = item.ItemAttributes.Author
                    url = item.DetailPageURL
                    print ("%s\n%s\n%s\n%s\n\n" % (line, title, author, url))
                else:
                    print ("%s : Book is None" % (line))
        print ("END %s" % (line))
        time.sleep(5)   # Amazon API呼び出しは1秒に1回以内に収めるためsleep
</pre>
<p>調べてみると、「root.Items.find(&#8216;Item&#8217;)」は、<br />
Itemが空の時Noneを返すということなので、<br />
「items.find(&#8216;Item&#8217;)」をitem_findに放り込んで<br />
これがNoneの場合は処理しないようにしました。</p>
<p>結果はというと、以下のようになりました。</p>
<pre class="lang:default decode:true " >
END Foundations Reading Library
END Penguin Readers Easystarts
END Oxford Bookworms Starters
END Macmillan Readers Starter
END Macmillan New Wave Readers Level 1
END Oxford Reading Tree
END Longman Literacy Land Story Street
END Macmillan Springboard
END Rookie Readers Fiction
END Cambridge Storybooks
END Longman Shared Reading
END Oxford Start with English Readers
END Longman Big and Little Books
END CTP Emergent Readers
END 100 English
END Sight Word Readers
END Time-to-Discover Readers
END Step into Reading Step 1
END Step into Reading Step 2
END Scholastic Reader Level1
END Scholastic Reader Level2
END My First I Can Read Books
END I Can Read Books Level 1
END Penguin Young Readers Level 1
END Ready-to-Read Pre-Level 1
END Ready-to-Read Level 1
END Ready-to-Read Level 2
END All Aboard Reading Picture Books
END All Aboard Reading Level 1
END Puffin Easy-to-Read Level 1
END Addison Wesley Big and Little Books
END Oxford Classic Tales
END Curious George Short Stories
END Dorling Kindersley Readers Level 1
END Dorling Kindersley Readers Level 2
END Oxford Dominoes Stage 0
END Penguin Young Readers Level 2
END Longman Chatterbox
END TL PM Readers
END HM Leveled Reading Grade 1
END The Very Hungry Caterpillar
END Good Night Moon
END Brown Bear, Brown Bear, What Do You See?
END 
</pre>
<p>結果は全滅・・・。<br />
一つもKindle Unlimitedにはないという結果に。</p>
<p>そしてなぜか「if (item is not None):」のelse部分を通ってくれなかったという謎も。</p>
<p>リストを広げて再取得してみることにします。</p><p>The post <a href="https://ichizo.biz/2016/12/20/english-kindle-unlimited.html">英語多読用リストがKindle Unlimitedに存在するか自動チェックしてみる</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://ichizo.biz/2016/12/20/english-kindle-unlimited.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">73</post-id>	</item>
		<item>
		<title>PythonでAmazonのKindle Unlimited情報を取得してみる</title>
		<link>https://ichizo.biz/2016/12/20/python-kindleunlimited.html</link>
					<comments>https://ichizo.biz/2016/12/20/python-kindleunlimited.html?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[一蔵]]></dc:creator>
		<pubDate>Tue, 20 Dec 2016 03:10:39 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Amazon Product Advertising API]]></category>
		<category><![CDATA[bottlenose]]></category>
		<category><![CDATA[Kindle Unlimited]]></category>
		<guid isPermaLink="false">http://ichizo.biz/?p=53</guid>

					<description><![CDATA[<p>Kindle Unlimitedって検索しずらい Kindl [&#8230;]</p>
<p>The post <a href="https://ichizo.biz/2016/12/20/python-kindleunlimited.html">PythonでAmazonのKindle Unlimited情報を取得してみる</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2>Kindle Unlimitedって検索しずらい</h2>
<p>Kindle Unlimitedを利用しているのですが、いまいち検索しずらいので<br />
該当の本がKindle Unlimitedで読めるのかを取得するプログラムを作ってみます。</p>
<p>PythonからAmazon Product Advertising APIを呼び出すプログラムを実装してみます。</p>
<p>環境は、「<a href="http://ichizo.biz/2016/12/13/anaconda.html">AnacondaでWindows上にPython環境を構築</a>」で構築したものを使用します。</p>
<p>Windows上でインストールしたAnacondaで一緒に入っているSyderを使用します。</p>
<p>Syderを立ち上げて、まずはプロジェクトを作成します。</p>
<p>メニューのProjectsから「New Project&#8230;」をクリックします。</p>
<p>プロジェクト名とプロジェクトで使用するフォルダを指定します。</p>
<h2>作成したいPythonプログラム</h2>
<p>作成したいプログラムは、書名で検索してその本がKindle Unlimitedに<br />
登録されているかを返すというものです。</p>
<p>現在、Kindle Unlimitedを利用中なのですが、<br />
Kindle Unlimitedだけを対象とした検索って<br />
いまいちやりずらいんです。</p>
<p>そこで、書名から検索してそれがKindle Unlimitedの対象になっているかを<br />
調べるプログラムを作ろうと思った次第です。</p>
<p>書名は1冊ではなく複数調べたいので、<br />
入力はテキストファイルにリストで書いておいて<br />
それを読み込むようにしたいと思います。</p>
<p>出力は、書名とそれがKindle Unlimitedに存在するかの真偽値を<br />
記載するようにすればよいでしょう。</p>
<h3>Amazon Product Advertising API用のライブラリを利用する</h3>
<p>Pythonには、Amazon Product Advertising API用のライブラリがあるようなので、それを利用させてもらいます。</p>
<p>まずはbottlenoseというライブラリをインストールします。</p>
<p>コマンドプロンプトを立ち上げる際に右クリックして、<br />
「その他」から「管理者として実行」をクリックします。</p>
<p>以下のコマンドを実行します。</p>
<pre class="lang:python decode:true " >pip install bottlenose</pre>
<p>これでインストールできました。</p>
<p>pipのバージョンが古いというメッセージが出ましたので、<br />
ついでにpipのバージョンも上げておきます。</p>
<pre class="lang:python decode:true " >python -m pip install --upgrade pip</pre>
<h3>Pythonプログラムのコーディング</h3>
<p>準備ができたので、さっそくPythonプログラムを実装します。<br />
今度はSpyderのエディタでコーディングを行います。</p>
<p>まずは簡単に、キーワードを指定して該当する書籍の 書名、著者名、URLを返すプログラムを書きます。</p>
<pre class="lang:python decode:true " >
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 19 14:49:19 2016

@author:
"""

from bottlenose import api
from lxml import objectify

AMAZON_ACCESS_KEY_ID = "アクセスキー"
AMAZON_SECRET_KEY = "シークレットキー"
AMAZON_ASSOC_TAG = "アソシエイトタグ"

amazon = api.Amazon(AMAZON_ACCESS_KEY_ID, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, Region = "JP")

def item_search (keywords, searchIndex="Books"):
    response = amazon.ItemSearch(Keywords=keywords, SearchIndex=searchIndex, ResponseGroup="Large")
    root = objectify.fromstring(response)
    return root.Items.Item

if __name__ == '__main__':

    for item in item_search('python'):
        title = item.ItemAttributes.Title
        author = item.ItemAttributes.Author
        url = item.DetailPageURL
        print ("%s\n%s\n%s\n\n" % (title, author, url))
</pre>
<p>lxmlはAnacondaに含まれていましたので、インストールする必要はありませんでした。</p>
<p>これで、「python」というキーワードに該当する本の<br />
タイトル、著者名、URLを取得することができました。</p>
<h3>Kindle Unlimitedを対象に検索する</h3>
<p>上記では、「searchIndex=&#8221;Books&#8221;」として、本のカテゴリから検索しましたが、<br />
次はKindle Unlimitedカテゴリ内を検索するようにします。</p>
<p>すでに実装されている方がいらっしゃったので、参考にさせていただきます。</p>
<p><a href="http://stonebeach-dakar.hatenablog.com/entry/Ruby%E3%81%A7Amazon%E3%81%AEAPI%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6Kindle_Unlimited%E6%9C%AC%E3%81%AE%E4%B8%80%E8%A6%A7%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E3%80%82" target="_blank">RubyでAmazonのAPIを使ってKindle Unlimited本の一覧を取得する。</a></p>
<p>こちらの方の記事によると、searchIndexを「KindleStore」にして<br />
browseNodeを追加してKindle UnlimitedのノードID「4486610051」を指定してやればよいようです。</p>
<p>で、実装してみました。</p>
<pre class="lang:default decode:true " >
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 19 14:49:19 2016

@author:
"""

from bottlenose import api
from lxml import objectify

AMAZON_ACCESS_KEY_ID = "アクセスキー"
AMAZON_SECRET_KEY = "シークレットキー"
AMAZON_ASSOC_TAG = "アソシエイトタグ"

KINDLE_UMLIMITED_NODE_ID = "4486610051"

amazon = api.Amazon(AMAZON_ACCESS_KEY_ID, AMAZON_SECRET_KEY, AMAZON_ASSOC_TAG, Region = "JP")

def item_search (keywords, searchIndex="KindleStore", browseNode=KINDLE_UMLIMITED_NODE_ID):
    response = amazon.ItemSearch(Keywords=keywords, SearchIndex=searchIndex, BrowseNode=browseNode, ResponseGroup="Large")
    root = objectify.fromstring(response)
    return root.Items.Item

if __name__ == '__main__':

    for item in item_search('python'):
        title = item.ItemAttributes.Title
        author = item.ItemAttributes.Author
        url = item.DetailPageURL
        print ("%s\n%s\n%s\n\n" % (title, author, url))
</pre>
<p>変更した個所は、item_searchでsearchIndexを「KindleStore」に変更して<br />
browseNodeを追加しただけです。</p>
<p>これを実行してみたところ、きちんとKindle Unlimited対象商品がリストに上がってきます。</p>
<p>これで、Amazon Product Advertising APIからKindle Unlimitedの電子書籍を取得することができました。</p>
<p>次回からは、いよいよ書名のリストからそれがKindle Unlimitedにあるかを取得するプログラムに進みます。</p><p>The post <a href="https://ichizo.biz/2016/12/20/python-kindleunlimited.html">PythonでAmazonのKindle Unlimited情報を取得してみる</a> first appeared on <a href="https://ichizo.biz">イチゾーのブログ</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://ichizo.biz/2016/12/20/python-kindleunlimited.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">53</post-id>	</item>
	</channel>
</rss>
