Perl で Amazon PA-API V5を使うのに便利なモジュール Amazon::PAApi5::Signature

Amazon Product Advertising API のバージョン切り替えの対応期限が迫っている件

PA-APIの利用制限がきつくなったのは、なんとか毎月幾ばくかの売上が立つことで利用停止されるのは避けられている状態でしたが、APIのバージョンアップに伴う旧バージョンの停止については対応を放置していました。

というのも、現在公式で提供されているSDKには、さすがにPerlのサポートがされておりません。まぁ、仕方ないところではあるのですが、自作スクリプトはPerlで作っていまだに使用しているものが結構な数あるので何とかできないものかと悩んでいる間に停止まで2ヶ月切るような状態に。

今ならPythonかなと環境は作って勉強は始めていますが今しばらく時間がかかりそうだったの、ひとまずはPerlでの実走を探してみることにしました。

Amazon::PAApi5::Signature モジュールで面倒な署名部分はクリアできる

こちらのモジュールで署名部分の作成を行ってくれるので、サンプルに従って使ってみれば何とかなるハズだけれど、このページのSYNOPSISのサンプルでは動きませんでした。

実際のサンプルはGitHubのリポジトリを参照して見つけました。

上記のスクリプトはAmazon.co.jpのデータベースから検索せいてくれるので日本語での使用ならこれをベースに改造していけば問題なさそう。

必要な情報はResourceで指定しないと返してくれないので、いちいち調べて指定しないといけないのが手間がかかるようになった印象です。まぁ、不要なデータを除いて軽量なデータを持ってこいよということなんでしょうけれど。Resourceの一覧はこれまた公式を参照です。

自作サンプル:JANコードを元に最安値・最高値を取得してみる

#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Amazon::PAApi5::Payload;
use Amazon::PAApi5::Signature;
use HTTP::Headers;
use LWP::UserAgent;
use Data::Dumper;
use Encode;
use JSON qw/encode_json decode_json/;

my $PARTNER_TAG = 'YOUR_PARTNER_TAG';
my $ACCESS_KEY = 'YOUR_ACCESS_KEY';
my $SECRET_KEY = 'YOUR_SECRET_KEY';

open my $FH,'JAN.txt';
while(<$FH>) {
my $JAN = $_;
chomp($JAN);
$JAN=~s/\s//g;
    {
        my $payload = Amazon::PAApi5::Payload->new(
            $PARTNER_TAG,
            'www.amazon.co.jp',
        )->to_json({
            Keywords    => $JAN,
            SearchIndex => 'All',
            Condition => 'Any',
            ItemCount   => 1,
            Resources   => [qw/
                ItemInfo.Title
                Offers.Listings.Price
                Images.Primary.Large
                Offers.Summaries.HighestPrice
                Offers.Summaries.LowestPrice
            /],
        });

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

        my $ua = LWP::UserAgent->new(
            default_headers => HTTP::Headers->new($sig->headers),
        );

        my $res = $ua->post($sig->req_url, Content => $sig->payload);
        my $data = decode_json($res->content);
        my $Title = $data->{SearchResult}->{Items}->[0]->{ItemInfo}->{Title}->{DisplayValue};
        my $Summaries = $data->{SearchResult}->{Items}->[0]->{Offers}->{Summaries};
        foreach(@$Summaries){
            my $Summary = $_;
            print encode('utf8',$Title)." ";
            print $Summary->{Condition}->{Value}." ";
            print $Summary->{HighestPrice}->{Amount}." ";
            print $Summary->{LowestPrice}->{Amount}."\n";
        }
    }
}
close($FH);
exit;

JANコードを列記したテキストファイを読み込んで、コンディション別の最安値・最高値を出力します。

実行例

元々ゲームなどの価格相場をチェックしたいなと思っていたので適当なJANコードのリストを作って動かしてみます(2020/01/10 時点のデータです)

% perl PA-API_SAMPLE.pl
キングダム ハーツIII - PS4 New 9990 2604
キングダム ハーツIII - PS4 Used 8100 1620
BIOHAZARD RE:2 Z Version  - PS4 New 14990 4500
BIOHAZARD RE:2 Z Version  - PS4 Used 9350 3580
SEKIRO: SHADOWS DIE TWICE - PS4 New 19990 6980
SEKIRO: SHADOWS DIE TWICE - PS4 Used 10600 4990
デビル メイ クライ 5 - PS4 New 14400 3400
デビル メイ クライ 5 - PS4 Used 9350 2596
【PS4】Days Gone  ( デイズゴーン ) 【早期購入特典なし】 【CEROレーティング「Z」】 New 10120 3849
【PS4】Days Gone  ( デイズゴーン ) 【早期購入特典なし】 【CEROレーティング「Z」】 Used 200000 2150
【PS4】ACE COMBAT™ 7: SKIES UNKNOWN New 24341 7480
【PS4】ACE COMBAT™ 7: SKIES UNKNOWN Used 9975 3550
新サクラ大戦 - PS4 New 15384 6900
新サクラ大戦 - PS4 Used 13100 5290
ポケットモンスター ソード -Switch New 14530 5080
ポケットモンスター ソード -Switch Used 11975 5050
New スーパーマリオブラザーズ U デラックス -Switch New 10789 5450
New スーパーマリオブラザーズ U デラックス -Switch Used 37552 4850
スーパーマリオメーカー 2 -Switch New 10789 5100
スーパーマリオメーカー 2 -Switch Used 11600 4720
スーパーマリオメーカー 2 -Switch Collectible 8980 8980
マリオカート8 デラックス - Switch New 10789 5400
マリオカート8 デラックス - Switch Used 53000 4980
リングフィット アドベンチャー -Switch New 29999 12843
リングフィット アドベンチャー -Switch Used 15565 12407
スーパー マリオパーティ - Switch New 11232 5520
スーパー マリオパーティ - Switch Used 11850 4800
ファイアーエムブレム 風花雪月 -Switch (『TCGファイアーエムブレム0』限定カード「士官学校の新任教師ベレト」 同梱) New 12593 6411
ファイアーエムブレム 風花雪月 -Switch (『TCGファイアーエムブレム0』限定カード「士官学校の新任教師ベレト」 同梱) Used 12475 5189

リングフィットアドベンチャー、クソ高ぇ……。

ItemCountを1にしているため検索結果は1件だけ返ってくるのですが、ゲームの場合は様々なバリエーションがあったりするので、実際は10程度にしてその中での最大値・最小値を取るようにした方が正確なデータが取れそう。変なバリエーションはたいていマーケットプレイス業者が作っているので、Amazonだけが登録したデータを取得することができたりすると良いですが、可能なのかな? 良い方法があったら教えていただきたいです。

あとは何回もテストしているとAPI制限にかかるのでキャッシュ機構なども入れて、出力結果を加工しやすい形で保存しておけば良いかな。

PerlでPA-API V5を使うというネタは、需要も少ないのかサンプルもそれほど多くは見つからなかったので誰かの参考にでもなれば幸いです。