MB-Support

パソコン初心者のサポートページ

バリューコマース アフィリエイトAPI
+ lastRSS が壊れました

 WEBサービスを利用するためのサンプルプログラムが提供されていて、それを使用してバリューコマース アフィリエイトAPIを使ってきましたが、いつしかデータを取得できなくなってしまいました。


バリューコマース アフィリエイトAPI は過去に初心者向けサンプルプログラム「Valuecommerce Product Search API Sample for PHP(2007/03/30 Ver 1.01)」を提供していました。 config.php、lastRSS.php、util.php からなるプログラムなのですが、右も左も分からなかった当時、とても便利で使わせていただきました。 もちろん HTML 形式で出力する部分は自分なりに加工して使っていました。


データが取得できないトラブルに遭遇

いつしかデータをうまく取得できないときがあり、それも不思議なふるまいをしていて、月曜日〜金曜日は問題なく動くのに、土曜日と日曜日はデータを取得できなくなったり、祝日当日と前後にデータが取れなくなったりと、奇妙なふるまいを確認しました。

しかしながら、放っておけば必ず直っていたので、ここ 1 年ほど静観していました。使い始めた当時はレスポンスが悪かったので、そんなに力を入れていなかったのも事実です。

ところが、1 週間ほど直らない状況が続き、何のトラブルなのかと興味が沸き、数年ぶりに公式サイトにアクセスした結果、サンプルプログラムの配布は終了しており、それがあった痕跡も見つかりませんでした。

サンプルプログラムは lastRSS.php を改良したもので、ソースを見ても私のスキルでは理解できませんでした。そこで、他の WEB サービスと同じく、自前で作ることになりました。


ひとりでできるもん...

lastRSS で扱っていたキャッシュ機能は、PHP PEAR Cache_Liteで代用して解決しました。忘れていた問題は REST による RSS に vcという名前空間が入っていること、3 種類の画像の取得方法が分からないことです。

vc: に関しては、2008年に公開した日記「バリューコマースウェブサービス + PHP + SimpleXML」に掲載したので、それを参考にしましたが、画像の取得方法は掲載内容を試しても失敗しました。


バリューコマースウェブサービス + PHP + SimpleXML


リクエストで RSS(xml) を取得

トークンや必要なパラメータを繋いで変数「$url」に格納します。

$xml = simplexml_load_string("$url");

これだと、以下のエラーが表示されました。

Entity: line 1: parser error : Start tag expected, ‘<’ not found

あぁ、ごめんなさいってことで、以下のようにします。

$apirss = @file_get_contents($url);
$xml = simplexml_load_string("$apirss");

試しに「$xml」をダンプしてみましょう。

var_dump  ($xml);

結果は...このページに掲載するソースは、公式サイトに掲載されている架空のデータです。

object(SimpleXMLElement)#3 (2) {
  ["@attributes"]=>
  array(1) {
    ["version"]=>
    string(3) "2.0"
  }
  ["channel"]=>
  object(SimpleXMLElement)#4 (6) {
    ["title"]=>
    string(45) "ValueCommerce Product Database Search Results"
    ["link"]=>
    string(28) "http://www.valuecommerce.com"
    ["description"]=>
    string(23) "Processing time: 197 ms"
    ["language"]=>
    string(2) "ja"
    ["copyright"]=>
    string(38) "Copyright 2019, ValueCommerce Co. Ltd."
    ["item"]=>
    array(10) {
      [0]=>
      object(SimpleXMLElement)#5 (4) {
        ["title"]=>
        string(172) "【Japan】 USB-IRL08"
        ["link"]=>
        string(167) "//ck.jp.ap.valuecommerce.com/servlet/referral?vs=(省略)"
        ["description"]=>
        string(212) "USBケーブル〔0.8m〕(ホワイト)"
        ["guid"]=>
        string(69) "http://www.sample.com"
      }
      (省略)
}

以上の結果から各 <item> のデータ「title」、「link」、「description」、「guid」などは見えますが、タグ名に「vc:」が含まれるデータは見えません。


<item>より上のvc:が含まれるデータを取得する

まずは<item>より上のデータに注目して、ページ送りリンクを作る際
<vc:resultcount> (商品の検索結果の合計件数)
<vc:pagecount> (合計ページ数)
<vc:page> (現在表示されている検索結果のページ番号)
などが必要と思われます。これらのデータを取得するには以下。

@$vc = $xml->channel->children('http://valuecommerce.com/pdb/rss/');

試しに「$vc」をダンプしてみましょう。

var_dump  ($vc);

結果は...このページに掲載するソースは、公式サイトに掲載されている架空のデータです。

object(SimpleXMLElement)#6 (11) {
  ["keyword"]=>
  string(5) "japan"
  ["adult"]=>
  string(1) "n"
  ["category"]=>
  string(11) "electronics"
  ["resultPerPage"]=>
  string(2) "20"
  ["sortBy"]=>
  string(5) "score"
  ["sortOrder"]=>
  string(4) "desc"
  ["page"]=>
  string(1) "1"
  ["resultcount"]=>
  string(5) "42144"
  ["pagecount"]=>
  string(4) "2108"
  ["mediaType"]=>
  string(3) "Web"
  ["status"]=>
  string(2) "OK"
}

<item>より上の「vc:」が含まれるデータが見えました。これを取り出すには、以下のようにします。

$resultPerPage = $vc->resultPerPage; //商品の検索結果の合計件数
$pagecount = $vc->pagecount; //合計ページ数
$page = $vc->page; //現在表示されている検索結果のページ番号

これを出力するには以下。

print("商品の検索結果の合計件数:{$resultPerPage}<br />"):
print("合計ページ数:{$pagecount}<br />"):
print("現在表示されている検索結果のページ番号:{$page}<br />"):

結果は以下。vc:のデータも取得できますね。もちろん、ページ送りリンクを作る前に、statusを取得してエラーの判別をした方がいいでしょう。

商品の検索結果の合計件数:42144
合計ページ数:2108
現在表示されている検索結果のページ番号:1

各<item>内のデータを取得する

<item>は複数あるので、まずは配列を反復処理する foreach を使いましょう。

$items = $xml->channel->item;
foreach ($items as $item) { 

処理A

}

上の処理Aの部分で、各<item>のデータを取得します。vc:が含まれないデータを取得するのは以下。

$itemName = $item->title;
$link = $item->link;
$description = $item->description;
$guid = $item->guid;

これを出力させるには以下。

print("タイトル:{$itemName}<br />"):
print("リンク:$link}<br />"):
print("解説:$description}<br />"):
print("またはグローバル一意識別子:$guid}<br />"):

結果は以下。特に問題はありませんね。

タイトル:【Japan】 USB-IRL08
リンク:"//ck.jp.ap.valuecommerce.com/servlet/referral?vs=(省略)
解説:USBケーブル〔0.8m〕(ホワイト)
またはグローバル一意識別子:http://www.sample.com

次は、各<item>のvc:が含まれるデータを取得します。先の方法と同じです。

$vcitem = $item->children('http://valuecommerce.com/pdb/rss/');
$vc_pvImg = $vci->pvImg; //adタグ(表示数カウント用)
$vc_price = number_format((int)$vci->price); //数字を3桁のカンマで区切る

これを出力させるには以下。

print("表示数カウント用:{$vc_pvImg}<br />"):
print("販売価格:{$vc_price}円<br />"):

結果は以下。各<item>のvc:が含まれるデータを取得できました。

表示数カウント用:<img src="http://ad.jp.ap.valuecommerce.com/(省略)
販売価格:1,470円

各<item>内の画像データを取得

リクエストで取得した RSS(xml) の画像データに関する部分は以下。ソースは公式サイトに掲載されている架空のデータを使いたかったのですが、現状の仕組みと違っていたので、本物のデータを加工しました。

<vc:image class="small" url="https://item-(省略)" height="74" width="74"/>
<vc:image class="large" url="https://item-(省略)" height="146" width="146"/>
<vc:image class="free" url="" height="" width=""/>

画像サイズは「small」「large」「free」の三種類で、画像のURLには拡張子がありません(そのままで画像は表示可能)。 高さと横幅の「height」と「widht」が含まれます。上の例では「free」サイズの画像データが存在しません。

このデータを抽出するのに XPath(XML Path Language) を使います。

$images = $item->xpath('vc:image'); //$images配列にvc:imageのデータを入れる
var_dump  ($images);

$images をダンプした結果が以下です。

array(3) {
  [0]=>
  object(SimpleXMLElement)#13 (1) {
    ["@attributes"]=>
    array(4) {
      ["class"]=>
      string(5) "small"
      ["url"]=>
      string(64) "https://item-shopping(省略)"
      ["height"]=>
      string(2) "76"
      ["width"]=>
      string(2) "76"
    }
  }
  [1]=>
  object(SimpleXMLElement)#14 (1) {
    ["@attributes"]=>
    array(4) {
      ["class"]=>
      string(5) "large"
      ["url"]=>
      string(64) "https://item-shopping(省略)"
      ["height"]=>
      string(3) "146"
      ["width"]=>
      string(3) "146"
    }
  }
  [2]=>
  object(SimpleXMLElement)#15 (1) {
    ["@attributes"]=>
    array(4) {
      ["class"]=>
      string(4) "free"
      ["url"]=>
      string(0) ""
      ["height"]=>
      string(0) ""
      ["width"]=>
      string(0) ""
    }
  }
}

3 つの画像データが配列$imagesに格納されていますね。$images[0]には「small」、$images[1]には「Large」、$images[2]には「free」が入っています。これらのデータを取り出すには以下。

$pic_small_class = $images[0]->attributes()->class;
$pic_small_url = $images[0]->attributes()->url;
$pic_small_height = $images[0]->attributes()->height;
$pic_small_width = $images[0]->attributes()->width;

これを出力させるには以下。

print("画像サイズ:{$pic_small_clas}<br />"):
print("画像URL:{$pic_small_url}<br />"):
print("画像の高さ:{$pic_small_height}<br />"):
print("画像の横幅:{$pic_small_width}<br />"):

結果は以下。small 画像のデータを取得できました。

画像サイズ:small
画像URL:https://item-shopping(省略)
画像の高さ:74
画像の横幅:74

二個目の画像データが欲しい時は、$images[1]とすれば良いでしょう。

$pic_small_class = $images[1]->attributes()->class;
$pic_small_url = $images[1]->attributes()->url;
$pic_small_height = $images[1]->attributes()->height;
$pic_small_width = $images[1]->attributes()->width;

表示するための文は省きますが結果は以下。large 画像のデータを取得できました。

画像サイズ:large
画像URL:https://item-shopping(省略)
画像の高さ:146
画像の横幅:146

HTMLを作るのであれば以下。

print("<a href=\"{$pic_small_url}\" height=\"{$pic_small_height}\" widht
=\"{$pic_small_width}\">"):

私がこのAPIに初めて触れたのは 2008 年頃だったと思いますが、その時は画像 URL やサイズが統一されていませんでした。 極端に大きなサイズ、そんな画像を読み込むだけでも負荷が掛かるような画像も存在していました。 今は統一されているのかも知れませんが、width(幅)のデータはしっかり解析した方が無難です。

小さい画像で width(幅)が 74pix を基準とするならば、それ以下のサイズは width(幅)と height(高さ)の情報をタグから消せば良いだけです。 もし 74pix より大きいサイズを取得したのあれば、width(幅)を 74 pix に変更して HTML を書けば良いでしょう。 その場合は横幅を基準に縮小されるので、あえて height(高さ)の情報を削除します。 以下参照。

<a href=\"画像のurl\" widht=\"74\">

いずれにしても、small の画像URLがあるのか? 無い場合は Large の画像URLはあるのか? width の値は存在するのか? width の値は想定内か? など、データを取得して条件分岐(if,else,elseif)で振り分けて加工する必要があるでしょう。


バリューコマース

追記:2019/10/01

Amazon の PA-API 4.0 から PA-API v5 に変更を促され、それまで使っていた HTTP(s)-GET/REST,SOAP から HTTPS-POST/JSON-RPC に変更を余儀なくされた結果、バリューコマース API も JSON フォーマットが利用できることを思い出し、RSS(xml) から JSONに変更しました。

JSONで受け取ったデータを json_decode() で連想配列にデコードすれば、foreach 1回で全てのデータを簡単に取り出せました。おそらくバリューコマース API は最初から JSON フォーマットに対応していたと思われ、なぜ私は今まで RSS(xml) を使っていたのかと...





Copyright © 2019 MB-Support パソコン初心者のサポートページ All Rights Reserved.

管理人のご挨拶プライバシーポリシー著作権/免責事項