Product Advertising API(以下AmazonAPI)はAmazonから商品データを取得することができるAPIです。
AmazonからデータをWordPressに投稿するコードを紹介します。アフィリエイトサイトや、プラットフォーム型サイトを作っている人にはおすすめです。
まず機能構築
まず最初に、実行を行う関数について見ていきましょう。
以下は、プラグインとして作成して有効化することをオススメします。
Amazonが提供している定数の準備
AmazonAPIで必ず必要になるアクセスキーやシークレットキーなどを定義します。
実際のキーの取得やアカウント登録などの手順についてはAmazon Webサービス入門 サービス利用の準備をご覧ください。
//Amazon共通の定数 define('AF','nets0f-22'); //トラッキング(自分で入力する。アフィリエイトID) define('AC','AAAAAAAAAAAAAAAA'); //アクセスキー(自分で入手する) define('SEC','abcdefghijklmnopqrstuvwxyz'); //シークレットキー(自分で入手する) define('URL','http://ecs.amazonaws.jp/onca/xml'); //リクエスト先のURL
商品データ取得するのに使うパラメータを取得
次は商品データ取得の際に必要となるパラメータを取得します。
中にあるget_key()という関数は、AmazonAPIに必要なタイムスタンプによる認証キーを生成しています。
//認証取得用関数 function urlencode_rfc3986($str) { return str_replace('%7E', '~', rawurlencode($str)); } function get_key($param){ ksort($param); $canonical_string = ''; foreach ($param as $k => $v) { $canonical_string .= '&'.urlencode_rfc3986($k).'='.urlencode_rfc3986($v); } $canonical_string = substr($canonical_string, 1); $parsed_url = parse_url(URL); $string_to_sign = "GETn{$parsed_url['host']}n{$parsed_url['path']}n{$canonical_string}"; $signature = base64_encode(hash_hmac('sha256', $string_to_sign, SEC, true)); // 返り値のURLにアクセスするとXMLが取得できます。 return URL.'?'.$canonical_string.'&Signature='.urlencode_rfc3986($signature); } //画像をサーバに保存するfunction //URLを投げたら指定したディレクトリに保存するだけ。。。。 function dl_image($url){ $tempimg = file_get_contents($url); file_put_contents(WP_CONTENT_DIR.'/upload/'.basename($url),$tempimg); unset($tempimg); return WP_CONTENT_DIR.'/upload/'.basename($url); }
パラメータを取得したので、実際にコンテンツを取得し、WordPressに保存する関数を作成
パラメータを取得したので、実際にAmazonAPIにアクセスして商品データを取得します。
カスタムフィールドにどの値を持つか、本文はどうするかなどは適宜変更してください。
//例:Amazon内のDVDカテゴリの中のアニメカテゴリから新着順に商品を取得する //ここから実際の取得処理------------------------------------------ //取得処理はwp_cronで動かしますのでadd_actionは不要です。 function get_amazon(){ $ct = array( '1' => '562020' //WP上のカテゴリID => Amazon上のカテゴリNo ); //ページカウンター //1ページずつ取っていきます。どこまで取得できたかをget_optionで保持している if(get_option('count')){ $i = get_option('count'); } else { $i = 1; add_option('count',1); } foreach($ct as $key=>$val){ //Amazonで必要なパラメーター類 $param = array( 'Service' => 'AWSECommerceService', 'AWSAccessKeyId' => AC, 'Operation' => 'ItemSearch', 'AssociateTag' => AF, 'ResponseGroup' => 'ItemAttributes,Images,Reviews', 'SearchIndex' => 'DVD',//DVDなど、任意の検索単語 'BrowseNode' => $val, 'Timestamp' => gmdate('Y-m-dTH:i:sZ'), 'ItemPage' => $i ); //先に定義した認証パラメータ付きURLを生成 $recurl = get_key($param); //ページカウントを進める //XML取得の途中で落ちてもいいようにforeach入る前にしてますがforeach後のほうが自然かも update_option('count',$i + 1); //XML取得 $xml = simplexml_load_file($recurl); foreach($xml->Items->Item as $key2=>$val2){ $actarray = array(); foreach($val2->ItemAttributes->Actor as $act){ $actarray[] = (String)$act; } //ここで記事として投稿処理を行う //ページスラッグがEANコード(ISBN的なものだと思われる)、タグをキャストとして投稿していますが適宜カスタムフィールドや本文などにしてもいい。 $postid = wp_insert_post(array( 'post_status' => 'publish', 'post_category' => array($key), 'post_title' => $val2->ItemAttributes->Title, 'post_name' => $val2->ItemAttributes->EAN, 'tags_input' => $actarray )); //重複チェック //同じ商品を取ってしまった場合、EANが同じになるので末尾に「-2」などと付加される。その「-」があれば一回投稿した記事を削除する。 //なお、無条件で「-」入りだと削除しているのでEAN以外をpost_nameにしていると間違って削除されるおそれがあります。 $temppost = get_page($postid); if(strpos($temppost->post_name, '-') === true){ wp_delete_post($postid); } else { //カスタムフィールドの付加 //商品URLや画像URLに加えて最終更新日としてtime()を追加している。理由は後述。 if($postid){ add_post_meta($postid,'DetailPageURL',(String)$val2->DetailPageURL,true); add_post_meta($postid,'SmallImage',(Array)$val2->SmallImage,true); add_post_meta($postid,'MediumImage',(Array)$val2->MediumImage,true); add_post_meta($postid,'LargeImage',(Array)$val2->LargeImage,true); add_post_meta($postid,'IFrameURL',(String)$val2->CustomerReviews->IFrameURL,true); add_post_meta($postid,'LastUpdate',(String)time(),true); //画像をローカルに保存する $smalimg = $val2->SmallImage->URL; $smalimg_local = dl_image($smalimg); $midimg = $val2->MediumImage->URL; $midimg_local = dl_image($midimg); $largeimg = $val2->LargeImage->URL; $largeimg_local = dl_image($largeimg); } } }//end foreach xml }//end foreach }//Amazonからの取得処理ここまで
Cronで定期的に処理をはしらsる
上記の処理を手動で走らせたり連続で走らせるとすぐにサーバが落ちたりAPIへのアクセスがブロックされるので、Cron(wp_cron)を使って定期的に自動実行させます。
AmazonAPIの利用規約では1時間2000リクエストとなっています。
//Cronの設定--------------------------------------------------------- //デフォルトのdailyやweeklyだけだと使い勝手が悪いのでいくつか足しておく //このcron_schedulesとwp_schedule_eventはテンプレ的にこのままでいいでしょう。 add_filter('cron_schedules','cron_add'); function cron_add($schedules){ $schedules['90min'] = array( 'interval' => 5400, 'display' => __( '90min' ) ); $schedules['100min'] = array( 'interval' => 6000, 'display' => __( '100min' ) ); $schedules['120min'] = array( 'interval' => 7200, 'display' => __( '120min' ) ); return $schedules; } //Cronに上記のget_amazon()を登録する //90分単位で動作します。 add_action('cron_for_amazon', 'get_amazon'); function my_activation() { if ( !wp_next_scheduled( 'cron_for_amazon' ) ) { wp_schedule_event(time(), '90min', 'cron_for_amazon'); } } add_action('wp', 'my_activation');
取得した商品データの更新
AmazonAPIの規約では、商品データをローカル(というか自分のサーバ)に保持することは許可されていますが、24時間以上保持することが禁止されています。
そこでデータ取得時に現在時刻をカスタムフィールドに保存していましたので、その時刻と現在時刻の差が24時間以上であれば再度商品取得処理を行うという処理を加えます。
これはCronではなくshutdownにフックしています。
誰かがアクセスしてそのときが24時間を超えていれば更新する、という仕組みです。
//ここからは商品データアップデート処理------------------------------------------ //Amazonは規約で24時間以上のキャッシュ保存が認められません。そこで前述のカスタムフィールドに加えている「LastUpdate」を見て、24時間が経過している場合は更新処理を行います。 function update_amazon(){ if(is_single()){ global $post; //LastUpdateと現在時刻の差が「60秒*60分*24時間」以上なら処理する if($post->LastUpdate 'AWSECommerceService', 'AWSAccessKeyId' => AC, 'Operation' => 'ItemLookup', 'AssociateTag' => AF, 'ResponseGroup' => 'ItemAttributes,Images,Reviews', 'IdType' => 'EAN', 'SearchIndex' => 'DVD', 'ItemId' => $post->post_name, //EANさえあれば商品は引っ張れる 'Timestamp' => gmdate('Y-m-dTH:i:sZ'), ); $recurl = get_key($param); $xml = simplexml_load_file($recurl); if($xml->Items->Item){ foreach($xml->Items->Item as $val2){ update_post_meta($postid,'DetailPageURL',(String)$val2->DetailPageURL); update_post_meta($postid,'SmallImage',(Array)$val2->SmallImage); update_post_meta($postid,'MediumImage',(Array)$val2->MediumImage); update_post_meta($postid,'LargeImage',(Array)$val2->LargeImage); update_post_meta($postid,'IFrameURL',(String)$val2->CustomerReviews->IFrameURL); update_post_meta($postid,'LastUpdate',(String)time()); //画像の差し替え //引数無しfile_put_contentsなので上書きされます $smalimg = $val2->SmallImage->URL; $smalimg_local = dl_image($smalimg); $midimg = $val2->MediumImage->URL; $midimg_local = dl_image($midimg); $largeimg = $val2->LargeImage->URL; $largeimg_local = dl_image($largeimg); } } } } }//func end //shutdownにフックすることで見る人にも優しい(はず) add_action('shutdown','update_amazon');
これで、完了です。