楽天商品ランキングAPIを使ってランキングを表示するCGIをつくってみたよ

春頃に作ったものを、色々直してみたので公開しておきます。サンプルにするなり使ってみるなり煮るなり焼くなり好きにしてください。

テンプレート方式なのでhtmlやcssが分ればデザインは割と自由に弄れます。デフォルトのテンプレートだと下のように表示されます。ブログのサイドバーやホームページ等にIFRAMEなどで組み込んで使うことを想定しています。

◇PC用ページ

◇携帯電話用ページ

 

 

ファイル構成

/rakurank/ ┐
           ├ config.cgi  … 設定ファイル
           ├ mb_tmpl.txt … 携帯電話用テンプレートファイル
           ├ noimg.gif   … 画像なし用画像ファイル
           ├ pc_tmpl.txt … PC用テンプレートファイル
           ├ r1.gif      … 第1位画像ファイル
           ├ r2.gif      … 第2位画像ファイル
           ├ r3.gif      … 第3位画像ファイル
           ├ r4.gif      … 第4位画像ファイル
           ├ r5.gif      … 第5位画像ファイル
           ├ rakurank.cgi… CGI本体
           ├ style.css   … スタイルシート
           └ 説明書.txt  … 説明書

 

説明書.txt

【楽天ウェブサービス】RAKUTEN WEBSERVICE
http://webservice.rakuten.co.jp/

楽天商品ランキングAPI (version:2010-08-05)
http://webservice.rakuten.co.jp/api/itemranking/
を利用したランキング表示CGIです。
Version 0.9.2

IFRAMEなどを利用してブログパーツの様に表示する事を前提に作成されています。

●機能
・楽天商品ランキングAPIを利用したランキング表示ページを生成します。
・ページはhtml形式のテンプレートになっているので、自由にカスタマイズできます。
・PC用のページと(utf8)携帯電話用のページ(utf8)を生成します。
・キャッシュ機能追記一度生成したページは24時間キャッシュします。
・テンプレートの編集で最大10位までのランキングを表示可能です。初期のテンプレートは3位までの表示なっています。
・CGIへのパラメータによって表示するランキングのジャンルを変更可能、一つのCGIで別々のページに別のジャンルのランキングを表示するような使用が可能。

●動作環境

このCGIは
・さくらインターネットの共用レンタルサーバ スタンダードプラン
・XREA
で動作することを確認しています。

●設置説明書

0.ダウンロードした圧縮ファイルを展開して出てきたrakurankというフォルダを
FTPソフトでそのまま自分が利用しているサーバにアップロードすることになります。
アップロードを行う前に以下の準備を行ってください。

1.config.cgiを文字コード[UTF8]に対応したテキストエディタで以下の部分について編集を行ってください。

以下ではさくらインターネットの共用レンタルサーバに設置する場合を例に上げて説明します。

●さくらインターネットの共用レンタルサーバではディレクトリ構成が
/home/自分のアカウントID/www
となっているので、wwwディレクトリ配下にrakurankをアップロードした場合$dirには以下のように設定します。
※ここでは便宜的にIDを「example」とします。

■CGIをアップロードしたディレクトリをフルパスで指定 (/から指定)
$dir            = ‘/home/example/www/rakurank’;

●さくらインターネットの場合
/home/example/www/rakurank
は実際にInternet Explorer等のブラウザでアクセスする場合のURLは
http://example.sakura.ne.jp/
となるので以下の様になります。
独自ドメインやサブドメインを利用してる場合はそれにあわせてください。

#■画像のある場所のURL (上のCGIをアップロードしたディレクトリに対応するURL)(http://から指定)
$img_url        = ‘http://example.sakura.ne.jp/rakurank’;

●以下には【楽天ウェブサービス】RAKUTEN WEBSERVICE
http://webservice.rakuten.co.jp/
で取得したアフィリエイトIDを設定します。

#■あなたの楽天アフィリエイトID
$affiliateId    = ‘xxxxxxxxnnnnnnnnaaaaaaaabbbbbbbb’;

●以下には【楽天ウェブサービス】RAKUTEN WEBSERVICE
http://webservice.rakuten.co.jp/
で取得したデベロッパーIDを設定します。

#■あなたのデベロッパーID
$developerId    = ‘aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa’;

●楽天の場合、商品名に長い文章が設定されていることが多い為、
適度な位置で省略する為に商品名の何文字まで表示するかを指定することができます。
初期値は『20』(文字)になっています。

#■商品名を頭から何文字まで表示するかを指定
$namelen        = 20;

●ジャンルIDが何も指定されていない時に自動的に使われるジャンルIDの初期値を
設定することができます。

ジャンルIDを簡単に調べるには
楽露店 – 楽天商品詳細検索
http://rakuroten.kumacchi.com/

≪ジャンルから探す≫
から各ジャンルのリンクを押してページを移動するとブラウザのアドレス欄に表示されている
URLの末尾から知ることができます。
http://rakuroten.kumacchi.com/genrecode/101240

#■デフォルトのジャンルID(ジャンルIDを指定しなかった時、自動的に使用されます。)
$defGenreId        = 401151;

2.設定を行って保存したらrakurank.cgiが入っているフォルダ(rakurank)ごとサーバーにFTPでアップロードしてください。

1位~5位の画像がr1.gif~r5.gifというファイルで添付されています。

画像がない商品の時はnoimg.gifが表示されるようになっています。noimg.gifも配布ファイルに含まれています。
現在は真っ白な画像です。
画像なしやno image等の文字を入れた画像に置き換えるなど好みにあわせてカスタマイズしてください。

3.Movable Type(MT)のサイドバーなどにランキング表示する設定
ランキングを表示したい箇所のテンプレートを開いて下記のタグを埋め込んでください。

<iframe src="http://example.sakura.ne.jp/rakurank/rakurank.cgi" width="400" height="500"  frameborder="0" scrolling="no"></iframe>

※URLは実際のパスにあわせてください。

ジャンルIDを指定する場合は、下のように?genreId=<ジャンルコード>としてください。上の様にgenreIDを指定していない場合は
設定で定義したデフォルトのジャンルID($defGenreIdの値)が使用されます。
<iframe src="http://example.sakura.ne.jp/rakurank/rakurank.cgi?genreId=101240" width="400" height="500"  frameborder="0" scrolling="no"></iframe>

4.Movable Typeで携帯電話用ページを生成している場合で携帯用のページにも広告を表示する場合

携帯用のページを生成しているテンプレートを開いて、ランキングを表示したい場所に下記のMTタグを埋め込んでください。
絶対パスは実際の環境にあわせてください。

<$mt:Include file="/home/example/www/rakurank/mb_401151.html"$>

携帯電話用のランキングページは
mb_<ジャンルID>.html
の形式で作成される文字コードutf8のhtmlファイルになります。
このページが作成されるタイミングはPC用ページが閲覧されたタイミングになるので
携帯用のページを見る前にPC用のページを見ている必要が有ります。

MovableType以外のブログやホームページの場合はそれらの環境に合わせた方法で工夫してください。

これで設定は完了です。実際に表示を確認してください。

●ライセンス
特にありません。自由にしてください。
自由に改造・改変・ソースの再利用・商用利用など特に連絡の必要は有りません。

●免責のお願い
ご利用は自己責任でお願いします。このプログラムを利用したことによる損害の発生についての保証はいたしかねます。

●その他
・プログラム中のKUMA TYPEのライセンス表示やリンクは消しても構いませんが、消さないでご利用いただけると嬉しいです。
・楽天のライセンス表示は規約上必要なものなので消してしまうと規約違反になります。

・プログラムの不具合はできるだけ修正したいと思いますが、環境の違いなどでこちらで再現できない問題は対応出来ないかと思います。

●FAQ
・Q1.キャッシュを削除したい
・A1.rakurankディレクトリの中にできた
pc_xxxx.html
mb_xxxx.html
というファイルを全て削除してください。

・Q2.ジャンルIDを指定しても表示されないランキングがある。
・A2.ランキングデータが存在しないジャンルIDは指定しても表示されません。

・Q3.出力文字コードを自由に変えたい。
・A3.ソース弄れば簡単に出来るので対応してないけど今後必要に応じて設定を追加するかも。

KUMA TYPE http://blog.kumacchi.com/
2010.09.09

config.cgi(設定ファイル)

#■設定ファイル

#■CGIをアップロードしたディレクトリをフルパスで指定 (/から指定)
$dir            = ‘/home/example/www/rakurank’;

#■画像のある場所のURL (上のCGIをアップロードしたディレクトリに対応するURL)(http://から指定)
$img_url        = ‘http://example.com/rakurank’;

#■あなたの楽天アフィリエイトID
$affiliateId    = ”;

#■あなたのデベロッパーID
$developerId    = ”;

#■商品名を頭から何文字まで表示するかを指定
$namelen        = 20;

#■デフォルトのジャンルID(ジャンルIDを指定しなかった時、自動的に使用されます。)
$defGenreId        = 401151;

###この下は消さないこと
1;

rakurank.cgi(プログラム本体)

#!/usr/local/bin/perl
#
#    楽天商品ランキング
#    2010.04.09
#        新規作成
#        楽天商品ランキングAPI (version:2009-04-15)
#    2010.04.11
#        ・このCGIだけで複数のジャンルIDをカバーできる様に仕様変更。
#        ・モバイル用にはモバイル用の情報を表示する用に修正。
#        ・商品名を切り出す設定が反映されていないのを修正。
#    2010.04.12
#        ・携帯用のページを生成するとき文字コードをSHIFT_JISで出力しないようにした。
#
#    2010.09.08
#        ・use utf8;するように修正
#        ・細々とした修正
#        ・軽くするためにCGI.pmを使用しないように修正
#        ・楽天ランキング APIをversion:2010-08-05に
#        ・restを3.0に
#    2010.09.09
#        ・設定を別ファイルに切り離した
#———————————————————————————-
use strict;
use warnings;
use utf8;
use LWP::Simple;
use XML::Simple;
use Encode;
use Encode qw/from_to/;
use Encode::Guess qw/ascii euc-jp shiftjis/;

my $VERSION        = ‘v.0.9.2’;

#グローバル変数の定義
our $dir;
our $img_url;
our $developerId;
our $affiliateId;
our $namelen;
our $defGenreId;

#設定ファイルの読み込み
require ‘config.cgi’;

my $errlog        = "$dir/errlog.cgi";
my $pctxt        = "$dir/pc_";
my $mbtxt        = "$dir/mb_";

# 楽天ウェブサービス
my $base_url    = ‘http://api.rakuten.co.jp/rws/3.0/rest’;

my $operation   = ‘ItemRanking’;
my $version     = ‘2010-08-05’;

my $shoplink    = "http://hb.afl.rakuten.co.jp/hgc/$affiliateId/?pc=";

my $req_url     = "$base_url?developerId=$developerId&operation=$operation&affiliateId=$affiliateId&version=$version";

#webサービスコピーライト
my $webservice=<<"EOF";
<!– Rakuten Web Services Attribution Snippet FROM HERE –>
<a href="http://webservice.rakuten.co.jp/" target="_blank">Supported by 楽天ウェブサービス</a>
<!– Rakuten Web Services Attribution Snippet TO HERE –>
EOF

my %in=();
my %cfg=();
&idecode();
#&loadconfig();

my $genreId = $in{‘genreId’} || $defGenreId;

#24時間キャッシュ
if((-e "$pctxt$genreId.html") && ((-M "$pctxt$genreId.html")*86400) < 86400){
    &pcdisp($genreId);
    exit(0);
}

#PC用ページ生成
#    ‘genreId’=>’401151’,    #ジャンルIDの指定
&makehtml({
    ‘genreId’=>"$genreId",
    ‘sex’=>”,                #0:男性 1;女性
    ‘age’=>”,                #年齢 10 20 30 40 50
    ‘carrier’=>”,            #PC用の情報かモバイル向けの情報か 0:PC 1:mobile
});

sleep(1);

#モバイル用ページ生成
#    ‘genreId’=>’401151’,    #ジャンルIDの指定
&makehtml_mb({
    ‘genreId’=>"$genreId",
    ‘sex’=>”,                #0:男性 1;女性
    ‘age’=>”,                #年齢 10 20 30 40 50
    ‘carrier’=>’1’,            #PC用の情報かモバイル向けの情報か 0:PC 1:mobile
});

&pcdisp($genreId);
exit(0);

#———————————————————-
#    PC用html 出力
#———————————————————-
sub makehtml{
    my $ref = shift;
    foreach my $key (keys %{$ref}){
        next if($ref->{$key} eq ”);
        $req_url .= "&$key=$ref->{$key}";
    }

    my $data = get($req_url);
    my $xmlsimple = XML::Simple->new();
    my $xml = $xmlsimple->XMLin($data,ForceArray=>[‘Item’]);

    #エラーチェック
    if($xml->{‘header:Header’}->{‘Status’} =~ /(ServerError|ClientError|Maintenance)/i){
        open(FILE,’>:encoding(utf8)’,"$errlog");
        print FILE $req_url,"\n";
        print FILE $data,"\n";
        close(FILE);
        exit(-1);
    }

    my $ary             = \$xml->{Body}{‘itemRanking:ItemRanking’}{‘Item’};
    my $title           = $xml->{Body}{‘itemRanking:ItemRanking’}{‘title’};
    my $lastBuildDate   = $xml->{Body}{‘itemRanking:ItemRanking’}{‘lastBuildDate’};

    #ループ
    foreach my $r (@{$$ary}) {
        $r->{‘itemName’}         = &textcut($r->{‘itemName’},$namelen);
        $r->{‘affiliateUrl’}   ||=”;
        $r->{‘smallImageUrl’}  ||= "$img_url/noimg.gif";
        $r->{‘mediumImageUrl’} ||= "$img_url/noimg.gif";
    }

    $/ = undef;
    open(FILE,'<:utf8′,"$dir/pc_tmpl.txt");
    my $pc_tmpl = <FILE>;
    close(FILE);
    $/ = "\n";

    for(my $i=1;$i<=10;$i++){
        $pc_tmpl =~ s/%itemName:$i%/${$$ary}[$i-1]->{itemName}/g;
        $pc_tmpl =~ s/%affiliateUrl:$i%/${$$ary}[$i-1]->{affiliateUrl}/g;
        $pc_tmpl =~ s/%smallImageUrl:$i%/${$$ary}[$i-1]->{smallImageUrl}/g;
        $pc_tmpl =~ s/%mediumImageUrl:$i%/${$$ary}[$i-1]->{mediumImageUrl}/g;
    }

    open(FILE,’>:encoding(utf8)’,"$pctxt$ref->{‘genreId’}.html");
    print FILE $pc_tmpl,’by <a href="http://blog.kumacchi.com/" target="_blank">KUMA TYPE</a><br>’,$webservice;
    close(FILE);
}

#———————————————————-
#    モバイル用html 出力
#———————————————————-
sub makehtml_mb{
    my $ref = shift;
    foreach my $key (keys %{$ref}){
        next if($ref->{$key} eq ”);
        $req_url .= "&$key=$ref->{$key}";
    }

    my $data = get($req_url);
    my $xmlsimple = XML::Simple->new();
    my $xml = $xmlsimple->XMLin($data,ForceArray=>[‘Item’]);

    #エラーチェック
    if($xml->{‘header:Header’}->{‘Status’} =~ /(ServerError|ClientError|Maintenance)/i){
        open(FILE,’>:encoding(utf8)’,"$errlog");
        print FILE $req_url,"\n";
        print FILE $data,"\n";
        close(FILE);
        exit(-1);
    }

    my $ary             = \$xml->{Body}{‘itemRanking:ItemRanking’}{‘Item’};
    my $title           = $xml->{Body}{‘itemRanking:ItemRanking’}{‘title’};
    my $lastBuildDate   = $xml->{Body}{‘itemRanking:ItemRanking’}{‘lastBuildDate’};

    #ループ
    foreach my $r (@{$$ary}) {
        $r->{‘itemName’}         = &textcut($r->{‘itemName’},$namelen);
        $r->{‘affiliateUrl’}   ||=”;
        $r->{‘smallImageUrl’}  ||= "$img_url/noimg.gif";
        $r->{‘mediumImageUrl’} ||= "$img_url/noimg.gif";
    }

    $/ = undef;
    open(FILE,'<:utf8′,"$dir/mb_tmpl.txt");
    my $mb_tmpl = <FILE>;
    close(FILE);
    $/ = "\n";

    for(my $i=1;$i<=10;$i++){
        $mb_tmpl =~ s/%itemName:$i%/${$$ary}[$i-1]->{itemName}/g;
        $mb_tmpl =~ s/%affiliateUrl:$i%/${$$ary}[$i-1]->{affiliateUrl}/g;
        $mb_tmpl =~ s/%smallImageUrl:$i%/${$$ary}[$i-1]->{smallImageUrl}/g;
        $mb_tmpl =~ s/%mediumImageUrl:$i%/${$$ary}[$i-1]->{mediumImageUrl}/g;
    }

#    open(FILE,’>:encoding(shiftjis)’,"$mbtxt$ref->{‘genreId’}.html");
    open(FILE,’>:encoding(utf8)’,"$mbtxt$ref->{‘genreId’}.html");
    print FILE $mb_tmpl,’by <a href="http://blog.kumacchi.com/mt4i2/mt4i.cgi">KUMA TYPE</a><br>’,$webservice;
    close(FILE);
}

#———————————————————-
#    文字省略
#    textcut (文字列,取り出す文字数)
#———————————————————-
sub textcut{
    my $str = shift || ”;
    my $num = shift || 20;

    my $utf8 = decode_utf8 $str;
    my $str_unit;
    if(length($utf8) > $num){
        $str_unit = substr($utf8,0,$num) . ‘…’;
    }else{
        $str_unit = $utf8;
    }

    $str_unit;
}

#———————————————————-
#    pc用表示
#———————————————————-
sub pcdisp{
    my $genreId = shift;
    $/ = undef;
    open(FILE,"$pctxt$genreId.html");
    my $HTML = <FILE>;
    close(FILE);

    print "Content-type: text/html\n\n";
    print << "EOF";
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="content-style-type" content="text/css">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
$HTML
</body>
</html>
EOF
    exit(0);
}

#———————————————————-
# 引数取得
#———————————————————-
sub idecode{
    my $QUERY_DATA=”;
    if($ENV{‘REQUEST_METHOD’} eq "POST"){
        read(STDIN,$QUERY_DATA,$ENV{‘CONTENT_LENGTH’});
    }else{
        $QUERY_DATA = $ENV{‘QUERY_STRING’};
    }
    my @argv = split(/&/,$QUERY_DATA);
    foreach(@argv){
        my ($arg,$val) = split(/=/);
        $val =~ tr/+/ /;
        $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("H2",$1)/eg;

        $val =~ s/&/&amp;/g;

        $val =~ s/</&lt;/g;
        $val =~ s/>/&gt;/g;

        $val =~ s/"/&quot;/g;
        $val =~ s/’/&apos;/g;

        $val =~ s/(?:\x0d|\x0a)//g;

        $val =~ s/\t//g;
        $val =~ s/\0//g;

        $in{"$arg"} = $val;
    }
}

pc_tmpl.txt(PC表示用テンプレートファイル)

<table width="362">
    <tr>
        <td><a href="%affiliateUrl:1%"><img src="%mediumImageUrl:1%"></a></td><td><div><img src="r1.gif"></div><div><a href="%affiliateUrl:1%">%itemName:1%</a></div></td>
    </tr>
    <tr>
        <td><a href="%affiliateUrl:2%"><img src="%mediumImageUrl:2%"></a></td><td><div><img src="r2.gif"></div><div><a href="%affiliateUrl:2%">%itemName:2%</a></div></td>
    </tr>
    <tr>
        <td><a href="%affiliateUrl:3%"><img src="%mediumImageUrl:3%"></a></td><td><div><img src="r3.gif"></div><div><a href="%affiliateUrl:3%">%itemName:3%</a></div></td>
    </tr>
</table>

mb_tmpl.txt(携帯電話表示用テンプレートファイル)

<table width="362">
    <tr>
        <td><a href="%affiliateUrl:1%"><img src="%smallImageUrl:1%"></a></td><td><div>1位</div><div><a href="%affiliateUrl:1%">%itemName:1%</a></div></td>
    </tr>
    <tr>
        <td><a href="%affiliateUrl:2%"><img src="%smallImageUrl:2%"></a></td><td><div>2位</div><div><a href="%affiliateUrl:2%">%itemName:2%</a></div></td>
    </tr>
    <tr>
        <td><a href="%affiliateUrl:3%"><img src="%smallImageUrl:3%"></a></td><td><div>3位</div><div><a href="%affiliateUrl:3%">%itemName:3%</a></div></td>
    </tr>
</table>

 

◆ダウンロード – rakurank_0_9_2.zip 20KB

●追記 2010.09.11

動かない場合の確認点

◆パーミッション(属性)の設定
特にパーミッションの設定は解説していませんが、
rakurankディレクトリは(700 又は 705など)
rakurank.cgiは(700 又は 705など)
と設定してください。その他のファイルはアップロードした時のデフォルトのままで多分問題ないと思います。

◆perlのバージョンの確認
5.8.x系より古いperlでは多分動かないです。

◆利用しているモジュールがサーバーにインストールされているか
どこでも動くようにモジュールは必要最小限の物に絞っていますが、下のモジュールがインストールされていないと動きません。

LWP::Simple 
XML::Simple

下のcgiをダウンロードしてアップロード後アクセスすることで、モジュールがインストールされているか自動でチェックできます。サンプル

◆ダウンロード – mchk.zip

動かない場合や不具合がある場合はコメントで質問してください。出来る範囲で対応します。質問時はできるだけ情報を出してください。

 

◆関連記事:【楽天ウェブサービス】楽天商品ランキングAPI – KUMA TYPE

◆関連記事:楽天商品ランキングAPIを使った売れ筋ランキング表示プログラムと作ってみた。 – KUMA TYPE

◆関連記事:楽天商品ランキングAPIを使ったperlサンプルソース – KUMA TYPE

タグ : , , ,