日記ブログ、または雑多なメモ

PHPとperlからAmazonアソシエイトのPA-APIを使って画像リンクを取得する




快感チェンジ単行本発売
広告

AmazonアソシエイトのPA-APIを使ってみる
 スーパーお久しぶりの小武です。 今年8月はC104開催、無事出展を終えて帰ってまいりました。 酷暑の中参加された皆様お疲れ様でした!参加の模様などについては小武総本家紹介ページに記事を載せておりますのでそちらもご覧くださればと。

 閑話休題。
 
 前回のブログ風日記の更新から6年ぶり? 基本的にtwitter(X)に活動報告をツイートする様になっていたのでこちらの更新は完全に止まっていたのだけど、つい最近Amazon PA-APIを使えるようにサイトを改造してみたのでその記事を書いてみようかと。 久しぶりに長文を書こうとするとへんてこな文を書いてしまうね!


 ところで最近Amazonアソシエイトで何が起こったかというと、
 
・これまで使えていた簡単画像リンク系のツールが使えなくなった
・文字リンクは従来どおり使えるので自前で画像を用意する分には今までどおり使えなくもない
・自動で画像リンクを作るにはAmazonの提供するPA-APIの利用が必要

 と簡単に画像リンクが取得できない仕様になり旧ツールで生成された画像リンクはリンク切れの絵が出るようになってしまった。 その他サードパーティの画像収集ライブラリもなくもないけどこちらも簡単に使えるものでもないしAmazon規定的に使って大丈夫なのかどうかはよくわからない。
 ということで自前で画像を用意するというのは実質無理に近く画像リンクを作りたければAmazonアソシエイトのツール「AmazonのPA-API」から直接商品情報を拾ってくる必要がある。 ただしAPIを使うには以下のような条件がある。
 
・JAVAかPHPまたはJSONにアクセスするスキルと知識が必要
・認証キーとパスが必要
・過去30日に一円以上のアフィリエイトの報酬が発生していること

 専門知識のスキルが必要になっている上になにげに一番敷居の高いのが3番目。 普通はそうそうアフィリエイトの収入は簡単には入らない。 アフィリエイトが発生していないときはツールを使っても
 
Amazonアソシエイトのツール・エラー画面

 
  こんな感じで「TooManyRequest」の表示が出てAPIは使えない。 条件を満たしていない間はおそらくリクエスト上限が「0」に設定されているのでこの表示になるらしい。 なお売上レポートで売上が発生しているのを確認できてもすぐ使えるようになるわけではなく1日程度待たないといけない模様。
 
 運良く(?)条件が揃ったら早速APIを触ってみよう。


認証キーとパス

 ここの認証キーの管理というところで「認証情報を追加」で作成するだけ。 その際表示されたシークレットキーは自分でどこかにメモしないと二度と見れなくなるので注意。


Amazon PA-APIにアクセスするperl編

 やっかいなことに当家の場合ここのブログはperlなのでperlからアクセスできる必要があるのだけどAmazon公式ではperlはサポートされていない。 しかしながら個人でperlのPA-APIライブラリを作成された方がいらっしゃるのでそれを使わせていただくことによって非常にお手軽にアクセスが可能になる。 ただしAPIを叩いて返ってくるのはJSONのデータのみなのでperlからJSONを解析できる必要がある。 なにはともあれありがたく使わせていただくことに。


まずPAApi5モジュールをインストール(当方はUbuntu 18.04.6 LTS)
% cpan Amazon::PAApi5::Signature


必要なヘッダ群(適当に足し引きする感じで)
#!/usr/bin/perl
use utf8;
binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");
use Encode::Guess;

use Amazon::PAApi5::Payload;
use Amazon::PAApi5::Signature;
use HTTP::Request::Common;
use LWP::UserAgent;
use JSON qw/from_json/;


必要な設定群
my $PARTNER_TAG = '自分のアソシエイトタグ';
my $ACCESS_KEY = 'アクセスキー';
my $SECRET_KEY = 'シークレットキー';


上記のライブラリを使用してPA-APIからアイテム検索するサブルーチン(参照元
sub searchApp5() {
    my ($key) = @_; #入力は検索語句(日本語可)

    my $payload = Amazon::PAApi5::Payload->new(
        $PARTNER_TAG,
        'www.amazon.co.jp',
    )->to_json({
        Keywords    => $key,
        SearchIndex => 'All',
        ItemCount   => 12, #検索最大数指定
        Resources   => [qw/
            Images.Primary.Large #要求リソース指定
            ItemInfo.Title #要求リソース指定
        /],
    });

    my $sig = Amazon::PAApi5::Signature->new(
        $ACCESS_KEY,
        $SECRET_KEY,
        $payload,
        {
            operation => 'SearchItems',
            host      => 'webservices.amazon.co.jp',
            region    => 'us-west-2',
        },
    );

    my $ua = LWP::UserAgent->new;
 
    my $req = POST $sig->req_url, $sig->headers, Content => $sig->payload;
    my $res = $ua->request($req);

    return $res->content; #返ってきたJSON文字列をそのまま返す
}


上記のサブルーチンからJSONを取得してそれを元にHTMLに画像リンクを書き出すコード
  $key = "岸見栄子"; #検索語句
  $res = &searchApp5(encode_utf8($key)); #UTF8エンコードしてから渡す
  $res = decode_utf8($res); #返ってきたJSON文字列をUTF8デコード

  my $json = from_json($res); #JSONをperlの多次元配列に変換

  my $items = @{$json->{SearchResult}->{Items}}; #返ってきたアイテム数取得
  for  ( $cnt = 0; $cnt < $items ; $cnt++ ) {
    my $det_url = $json->{ItemResult}->{Items}->[$cnt]->{DetailPageURL}; #アイテムURL
    my $img_url = $json->{ItemResult}->{Items}->[$cnt]->{Images}->{Primary}->{Large}->{URL}; #画像URL
    my $title = $json->{ItemResult}->{Items}->[$cnt]->{ItemInfo}->{Title}->{DisplayValue}; #アイテムタイトル

    print <<"End"; #HTMLに出力
          <a href="${det_url}" title="${title}" target="_blank">
            <img src="${img_url}" alt="${title}">
          </a>
          <a href="${det_url}" title="${title}" target="_blank">${title}</a>
End
  }#アイテム数分繰り返し

 以上のような感じ。 アイテム情報取得(GetItems)もだいたい似たような感じで処理できる。


Amazon PA-APIにアクセスするphp編

 phpの場合は公式でサポートされているので公式ページの「Code snippets」というところの「PHP」の部分のコードをそのまんま持ってきて自分のサーバーで動かすとJSONが簡単に取得できるのでファイルに「名前.json」として保存でもしておけばいつでも活用できる。
 
 ということでここでは保存したJSONデータからアイテム情報を読み出すコードを書いておく。

SearchItemsで取得した内容を「items.json」に保存、phpからそのファイルを読み込んで画像リンクをHTMLに出力するコード
  $res = file_get_contents("items.json"); //ファイル読み込み
  $json = json_decode($res,true); //jsonをphpの多次元配列に変換
  $itemCnt = count($json['SearchResult']['Items']); //アイテム数取得
  for ( $i = 0; $i < $itemCnt; $i++) {
    $detUrl = $json['SearchResult']['Items'][$i]['DetailPageURL']; //アイテムURL
    $imageUrl = $json['SearchResult']['Items'][$i]['Images']['Primary']['Large']['URL']; #画像URL
    $itemTitle = $json['SearchResult']['Items'][$i]['ItemInfo']['Title']['DisplayValue']; #アイテムタイトル
    print <<< End
          <a href="${detUrl}" title="${itemTitle}" target="_blank">
            <img src="${imageUrl}" alt="${itemTitle}">
          </a>
          <a href="${detUrl}" title="${itemTitle}" target="_blank">${itemTitle}</a>
End;
  } //アイテム数分繰り返し
?>

 公式サポートされているだけにデータの取得自体は簡単。 ただしJSONの変換や多次元配列を理解しようとするとちょっとややこしい。 リクエストして返ってくるレスポンスのjsonの構造は公式のドキュメントページに載っているので必要な方は確認してみてくだされ。 APIへのリクエスト数は上限が決まっているので常にリアルタイムで要求する必要がないのであれば取得したjsonを保存しておいてキャッシュとして使うといいと思う。
 それはそれとして、なぜかperlとphpで変数の命名規則がなんとなく自分の中で自然と変わる不思議。

 

- C'sGallery Blogっぽく見えるシステム3.2 -
小武 (管理人) eta2@tim.hi-ho.ne.jp