Amazonの商品検索ウィジェットが文字化けするので自作してみた part3

元々はAmazonの商品検索ウィジェットが文字化けするので仕方なく自分用に作ったPHPスクリプトですが、実際使って頂いた方からのフィードバックがあると嬉しいものですね。

SearchIndexの指定ができると便利、とのご要望を頂いたので機能追加してみました。

自作Amazon商品検索ウィジェットの追加機能

  • data-searchindex属性でAmazonのSearchIndexを指定できるように変更。
  • data-browsenodeid属性でAmazonのBrowseNodeIdを指定できるように変更。
  • data-update属性を追加し、キャッシュを強制的に更新できる機能を追加。

あと細々とした修正とCSSのイケてない部分の修正もちょろっとしてあります。

自作Amazon商品検索ウィジェットの使い方

HTML部分

■すべてのカテゴリーから検索する例

<div class="amazon-search" data-keywords="PHP"></div>

■SearchIndexを指定する例

<div class="amazon-search" data-keywords="PHP" data-searchindex="Books"></div>

■BrowseNodeIdを指定する例

<div class="amazon-search" data-keywords="PHP" data-browsenodeid="465392"></div>

■キャッシュを強制更新する例

<div class="amazon-search" data-keywords="PHP" data-update="1"></div>

data-searchindex / data-browsenodeid / data-update はそれぞれ単独でも組み合わせても使用可能です。

JavaScriptとCSSの部分

<script src="amazon_search.js" async></script>
<link rel="stylesheet" href="amazon_search.css">

外部ファイル化しましたので上のような書き方をしていますが、従来どおりJavaScriptとCSSをテンプレート等に貼り付けても構いません。

実行例

AmazonのSearchIndexとブラウズノードについて

使用できるSearchIndexの一覧は下記の PAAPI v5 マニュアルに記載があります。

https://webservices.amazon.com/paapi5/documentation/locale-reference/japan.html

ブラウズノードの一覧についてはAPIで取得できなくもないのですが、膨大な量になるため、下記のAmazonページから探したほうが早いかと思います。

https://www.amazon.co.jp/gp/site-directory

このサイトマップから、例えば「本」を選んだとします。

するとアドレスバーに

https://www.amazon.co.jp/本-通販/b?ie=UTF8&node=465392&ref_=sd_allcat_jb

というような表記がされていると思いますが、node=以降にかかれている赤字部分がブラウズノードIDです。

SearchIndexではざっくりとしたジャンル指定しか出来ませんので、より細かい指定がしたい場合にはブラウズノードIDを指定すると良いでしょう。

ダウンロード先

長々しい記事だと読むのも大変だと思い、PHPスクリプト、JavaScript、CSSをZIPにまとめてアップしておきました。ご自由に改変してお使いください。

少なくともPHP上部に書かれているアクセスキーやアソシエイトタグの変更は必須です。

https://blog.ver001.com/download/amazon_search_20200529.zip

ソースコード

ダウンロードや解凍は面倒なんじゃあ!とか、WordPressの管理ページで貼り付けるからコードそのままアップしてくれたほうが楽!という方のためにソースも貼り付けておきます。ちょっと長いので、不要な方はスルー推奨。

PHPスクリプト (amazon_search.php)

<?php
/*****************************************************************************************
 * Amazon商品検索ウィジェットっぽいことをするPHPスクリプト
 *
 *****************************************************************************************
 * 使用例:
 * <div class="amazon-search" data-keywords="PHP" data-searchindex="Books"></div>
 *****************************************************************************************/
///////////////////////////////////////////////////////////////////////////////////////////
// 設定部分
///////////////////////////////////////////////////////////////////////////////////////////
//Amazon PAAPIの設定
$cfg['AWSAccessKeyId'] = "[アクセスキー]";
$cfg['AWSSecretAccessKeyId'] = "[シークレットアクセスキー]";
$cfg['AssociateTag'] = "[アソシエイトタグ]";
//キャッシュ用データベース設定
$cfg['DB_FILE'] = 'amazon_search.db';
$cfg['DB_OPTION'] = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_TIMEOUT => 20);
//キャッシュ保持日数
$cfg['CACHE_TERM'] = "-3 days";
//検索結果の上部に表示するAmazonアイコン画像
$cfg['AMAZON_ICON'] = 'assocbutt_or_amz.png';
///////////////////////////////////////////////////////////////////////////////////////////

//特定URL(運営サイト)からのアクセスしか受け付けないようにしたほうが良いと思う
//if (substr_compare($_SERVER['HTTP_REFERER'], 'https://example.com', 0, 19) !== 0) exit();

//PHPスクリプトを別ドメインに置く場合はAccess-Control-Allow-Originを忘れずに
//header('Access-Control-Allow-Origin:https://example.com');

if (!isset($_GET['keywords'])) exit();
$keywords = $_GET['keywords']; //←必要に応じてサニタイズ処理を

//キャッシュ用データベースの準備
$pdo = connectDB();
//キャッシュ取得または生成
genAmazonCache($pdo, $keywords);
//キャッシュから検索結果を表示
viewAmazonResult($pdo, $keywords);

/************************************************
 * データベースを開く
 * なければないで作る
 ************************************************/
function connectDB()
{
	global $cfg;
	//キャッシュ用のDBファイルがない場合は作る
	if (!file_exists($cfg['DB_FILE'])) {
		$pdo = new PDO('sqlite:'.$cfg['DB_FILE'], '', '', $cfg['DB_OPTION']);
		//キャッシュ用テーブルの準備(1つはキーワードと更新日の保存用、もう1つは商品データ用)
		$query = "CREATE TABLE 'amazon_search_keywords' (".
				 " keywords text PRIMARY KEY,".
				 " update_date datetime);";
		$pdo->query($query);
		$query = "CREATE TABLE 'amazon_search_item' (".
				 " keywords text,".
				 " asin text,".
				 " title text,".
				 " brand text,".
				 " model text,".
				 " image_s text,".
				 " image_m text,".
				 " image_l text,".
				 " feature text,".
				 " price integer);";
		$pdo->query($query);
		//インデックスも張っておく
		$query = "CREATE INDEX amazon_search_item_index ON amazon_search_item(keywords)";
		$pdo->query($query);
	} else {
		$pdo = new PDO('sqlite:'.$cfg['DB_FILE'], '', '', $cfg['DB_OPTION']);
	}
	return $pdo;
}
/************************************************
 * キャッシュをチェックし、なければ(あるいは古ければ)
 * Amazonからデータをひっぱってきてキャッシュを作る感じ
 ************************************************/
function genAmazonCache($pdo, $keywords)
{
	global $cfg;

	//キーワードキャッシュがあるか確認
	$stmt = $pdo->prepare('SELECT update_date FROM amazon_search_keywords WHERE keywords=?');
	$stmt->bindValue(1, $keywords);
	$stmt->execute();
	//更新フラグ
	$flg_update = false;
	if ($row = $stmt->fetch()) {
		if ( (isset($_GET['update']) && $_GET['update'] == '1') ||
			 ($row['update_date'] <= date("Y-m-d H:i:s", strtotime($cfg['CACHE_TERM'])))) {
			//キャッシュがあったとしても一定期間以上経っていた場合は更新する
			//2020-05-28 また、update=1が指定されていた場合は期間に関わらずキャッシュを更新する
			$flg_update = true;
			$stmt = $pdo->prepare('UPDATE amazon_search_keywords SET update_date=? WHERE keywords=?');
			$stmt->bindValue(1, date('Y-m-d H:i:s'));
			$stmt->bindValue(2, $keywords);
			$stmt->execute();
		}
	} else {
		$flg_update = true;
		$row = array();
		$row['keywords'] = $keywords;
		$row['update_date'] = date('Y-m-d H:i:s');
		pdoInsert($pdo, 'amazon_search_keywords', $row);
	}
	if ($flg_update) {
		//PAAPIからJSON取得
		$json = getAmazonSearchItems($keywords);
		$aws = json_decode($json);
		$pdo->beginTransaction();
		//キャッシュのクリア
		$stmt = $pdo->prepare('DELETE FROM amazon_search_item WHERE keywords=?');
		$stmt->bindValue(1, $keywords);
		$stmt->execute();
		//キャッシュに格納
		setAmazonItem($pdo, $keywords, $aws);
		$pdo->commit();
	}
}
/************************************************
 * 検索結果を表示
 *
 ************************************************/
function viewAmazonResult($pdo, $keywords)
{
	global $cfg;
	$stmt = $pdo->prepare('SELECT * FROM amazon_search_item WHERE keywords=?');
	$stmt->bindValue(1, $keywords);
	$stmt->execute();

	$html = '';
	$html .= '<div class="amazon_search">';
	$search_url = 'https://www.amazon.co.jp/s/ref=as_li_ss_tl?k='.urlencode($keywords).'&tag='.$cfg['AssociateTag'];
	$html .= '<a href="'.$search_url.'"><img src="'.$cfg['AMAZON_ICON'].'"></a>&nbsp;<a href="'.$search_url.'">'.htmlspecialchars($keywords).'</a><br>';
	$html .= '<section style="display:inline-block;text-align:center;">';
	while ($row = $stmt->fetch()) {
		$url = 'https://www.amazon.co.jp/dp/'.htmlspecialchars($row['asin']).'/?tag='.$cfg['AssociateTag'];
		$html .= '<div>';
		$html .= '<a href="'.$url.'" title="'.htmlspecialchars($row['title']).'" target="_blank">';
		$html .= '<img src="'.$row['image_m'].'"><br>';
		$html .= '<p>'.htmlspecialchars($row['title']).'</p>';
		$html .= '</a>';
		$html .= '<p>'.number_format($row['price']).'円</p>';
		$html .= '</div>';
	}
	$html .= '</section>';
	$html .= '<footer><a href="'.$search_url.'">もっと見る</a></footer>';
	$html .= '</div>';
	echo $html;
}
/************************************************
 * Amazon PAAPIから取得したデータをDBへ格納
 *
 ************************************************/
function setAmazonItem($pdo, $keywords, $aws)
{
	if (!isset($aws->SearchResult->Items)) return;
	foreach ($aws->SearchResult->Items as $item) {
		$row_upd = array();
		$row_upd['keywords'] = $keywords;
		$row_upd['asin'] = $item->ASIN;
		$row_upd['title'] = mb_substr($item->ItemInfo->Title->DisplayValue, 0, 255);
		$row_upd['brand'] = @$item->ItemInfo->ByLineInfo->Brand->DisplayValue;
		$row_upd['model'] = isset($item->ItemInfo->ManufactureInfo->Model) ? $item->ItemInfo->ManufactureInfo->Model->Label : '';
		//画像
		$row_upd['image_s'] = @$item->Images->Primary->Small->URL;
		$row_upd['image_m'] = @$item->Images->Primary->Medium->URL;
		$row_upd['image_l'] = @$item->Images->Primary->Large->URL;
		if ($row_upd['image_s'] == '') $row_upd['image_s'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
		if ($row_upd['image_m'] == '') $row_upd['image_m'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
		if ($row_upd['image_l'] == '') $row_upd['image_l'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
		$row_upd['price'] = @$item->Offers->Summaries[0]->LowestPrice->Amount;
		pdoInsert($pdo, "amazon_search_item", $row_upd);
	}
}
/************************************************
 * 連想配列からINSERT文を実行する
 * (何度も同じ項目名を書くのが面倒なため)
 ************************************************/
function pdoInsert($pdo, $tablename, $row)
{
	$keys1 = '';
	$keys2 = '';
	foreach ( $row as $key => $value ) {
		$keys1 .= $key . ','; //項目名を列挙
		$keys2 .= ':' . $key . ','; //プレースホルダを列挙
	}
	$keys1 = substr($keys1, 0, -1);
	$keys2 = substr($keys2, 0, -1);
	$stmt = $pdo->prepare('INSERT INTO '.$tablename.' ('.$keys1.') VALUES ('.$keys2.')');
	$stmt->execute($row);
}
/************************************************
 * ここから下はAmazon PAAPI 5.0のScratchpadで生成されるコードほぼそのまんまです
 * https://webservices.amazon.co.jp/paapi5/scratchpad/index.html
 ************************************************/
function getAmazonSearchItems($keywords) {
	global $cfg;
	$serviceName="ProductAdvertisingAPI";
	$region="us-west-2";
	$accessKey=$cfg['AWSAccessKeyId'];
	$secretKey=$cfg['AWSSecretAccessKeyId'];

	$payload = '{'.
				' "Keywords": "'.$keywords.'",'.
				' "PartnerTag": "'.$cfg['AssociateTag'].'",'.
				' "PartnerType": "Associates",'.
				' "Marketplace": "www.amazon.co.jp",'.
				' "Resources": ['.
				' "Images.Primary.Small",'.
				' "Images.Primary.Medium",'.
				' "Images.Primary.Large",'.
				' "Offers.Summaries.LowestPrice",'.
				' "ItemInfo.Title",'.
				' "ItemInfo.ByLineInfo",'.
				' "ItemInfo.ManufactureInfo",'.
				' "ItemInfo.ProductInfo"'.
				' ]';
	if (isset($_GET['searchindex'])) { //2020-05-28 SearchIndex対応
		$payload .= ',"SearchIndex":"'.$_GET['searchindex'].'"';
	}
	if (isset($_GET['browsenodeid'])) { //2020-05-28 BrowseNodeId対応
		$payload .= ',"BrowseNodeId":"'.$_GET['browsenodeid'].'"';
	}
	$payload .= '}';

	$host="webservices.amazon.co.jp";
	$uriPath="/paapi5/getitems";
	$awsv4 = new AwsV4 ($accessKey, $secretKey);
	$awsv4->setRegionName($region);
	$awsv4->setServiceName($serviceName);
	$awsv4->setPath ($uriPath);
	$awsv4->setPayload ($payload);
	$awsv4->setRequestMethod ("POST");
	$awsv4->addHeader ('content-encoding', 'amz-1.0');
	$awsv4->addHeader ('content-type', 'application/json; charset=utf-8');
	$awsv4->addHeader ('host', $host);
	$awsv4->addHeader ('x-amz-target', 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems');
	$headers = $awsv4->getHeaders ();
	$headerString = "";
	foreach ( $headers as $key => $value ) {
		$headerString .= $key . ': ' . $value . "\r\n";
	}
	$params = array (
			'http' => array (
				'header' => $headerString,
				'method' => 'POST',
				'content' => $payload
			)
		);
	$stream = stream_context_create ( $params );
	$fp = @fopen ( 'https://'.$host.$uriPath, 'rb', false, $stream );
	if (! $fp) {
		throw new Exception ( "Exception Occured" );
	}
	$response = @stream_get_contents ( $fp );
	if ($response === false) {
		throw new Exception ( "Exception Occured" );
	}
	return $response;
}
class AwsV4 {
	private $accessKey = null;
	private $secretKey = null;
	private $path = null;
	private $regionName = null;
	private $serviceName = null;
	private $httpMethodName = null;
	private $queryParametes = array ();
	private $awsHeaders = array ();
	private $payload = "";
	private $HMACAlgorithm = "AWS4-HMAC-SHA256";
	private $aws4Request = "aws4_request";
	private $strSignedHeader = null;
	private $xAmzDate = null;
	private $currentDate = null;
	public function __construct($accessKey, $secretKey) {
		$this->accessKey = $accessKey;
		$this->secretKey = $secretKey;
		$this->xAmzDate = $this->getTimeStamp ();
		$this->currentDate = $this->getDate ();
	}
	function setPath($path) {
		$this->path = $path;
	}
	function setServiceName($serviceName) {
		$this->serviceName = $serviceName;
	}
	function setRegionName($regionName) {
		$this->regionName = $regionName;
	}
	function setPayload($payload) {
		$this->payload = $payload;
	}
	function setRequestMethod($method) {
		$this->httpMethodName = $method;
	}
	function addHeader($headerName, $headerValue) {
		$this->awsHeaders [$headerName] = $headerValue;
	}
	private function prepareCanonicalRequest() {
		$canonicalURL = "";
		$canonicalURL .= $this->httpMethodName . "\n";
		$canonicalURL .= $this->path . "\n" . "\n";
		$signedHeaders = '';
		foreach ( $this->awsHeaders as $key => $value ) {
			$signedHeaders .= $key . ";";
			$canonicalURL .= $key . ":" . $value . "\n";
		}
		$canonicalURL .= "\n";
		$this->strSignedHeader = substr ( $signedHeaders, 0, - 1 );
		$canonicalURL .= $this->strSignedHeader . "\n";
		$canonicalURL .= $this->generateHex ( $this->payload );
		return $canonicalURL;
	}
	private function prepareStringToSign($canonicalURL) {
		$stringToSign = '';
		$stringToSign .= $this->HMACAlgorithm . "\n";
		$stringToSign .= $this->xAmzDate . "\n";
		$stringToSign .= $this->currentDate . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "\n";
		$stringToSign .= $this->generateHex ( $canonicalURL );
		return $stringToSign;
	}
	private function calculateSignature($stringToSign) {
		$signatureKey = $this->getSignatureKey ( $this->secretKey, $this->currentDate, $this->regionName, $this->serviceName );
		$signature = hash_hmac ( "sha256", $stringToSign, $signatureKey, true );
		$strHexSignature = strtolower ( bin2hex ( $signature ) );
		return $strHexSignature;
	}
	public function getHeaders() {
		$this->awsHeaders ['x-amz-date'] = $this->xAmzDate;
		ksort ( $this->awsHeaders );
		// Step 1: CREATE A CANONICAL REQUEST
		$canonicalURL = $this->prepareCanonicalRequest ();
		// Step 2: CREATE THE STRING TO SIGN
		$stringToSign = $this->prepareStringToSign ( $canonicalURL );
		// Step 3: CALCULATE THE SIGNATURE
		$signature = $this->calculateSignature ( $stringToSign );
		// Step 4: CALCULATE AUTHORIZATION HEADER
		if ($signature) {
			$this->awsHeaders ['Authorization'] = $this->buildAuthorizationString ( $signature );
			return $this->awsHeaders;
		}
	}
	private function buildAuthorizationString($strSignature) {
		return $this->HMACAlgorithm . " " . "Credential=" . $this->accessKey . "/" . $this->getDate () . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "," . "SignedHeaders=" . $this->strSignedHeader . "," . "Signature=" . $strSignature;
	}
	private function generateHex($data) {
		return strtolower ( bin2hex ( hash ( "sha256", $data, true ) ) );
	}
	private function getSignatureKey($key, $date, $regionName, $serviceName) {
		$kSecret = "AWS4" . $key;
		$kDate = hash_hmac ( "sha256", $date, $kSecret, true );
		$kRegion = hash_hmac ( "sha256", $regionName, $kDate, true );
		$kService = hash_hmac ( "sha256", $serviceName, $kRegion, true );
		$kSigning = hash_hmac ( "sha256", $this->aws4Request, $kService, true );
		return $kSigning;
	}
	private function getTimeStamp() {
		return gmdate ( "Ymd\THis\Z" );
	}
	private function getDate() {
		return gmdate ( "Ymd" );
	}
}
?>

JavaScript (amazon_search.js)

document.querySelectorAll('.amazon-search').forEach(e => {
	let xhr = new XMLHttpRequest();
	let url = 'amazon_search.php?keywords=' + encodeURIComponent(e.dataset.keywords);
	if (e.dataset.update !== undefined) url += '&update=' + e.dataset.update;
	if (e.dataset.searchindex !== undefined) url += '&searchindex=' + e.dataset.searchindex;
	if (e.dataset.browsenodeid !== undefined) url += '&browsenodeid=' + e.dataset.browsenodeid;
	xhr.open('GET', url, true);
	xhr.onload = function () { e.innerHTML = this.responseText; }
	xhr.send();
});

CSS (amazon_search.css)

div.amazon_search { border:1px solid #cccccc;border-top:3px solid #ff8000;border-radius:4px;padding:4px 1em 0 1em; }
div.amazon_search img:nth-child(1) { display:inline-block;height:20px;border:0;padding:0;vertical-align:middle; }
div.amazon_search a:nth-of-type(2) { display:inline-block;font-size:9pt;text-decoration:none;margin:0 0 14px; }
div.amazon_search div { position:relative;display:inline-block;margin:0 6px 2px 0; }
div.amazon_search div img:nth-child(1) { width:120px;height:120px;object-fit:cover; }
div.amazon_search div:hover p { transform:scale(1.2);transition-duration:0.3s; } 
div.amazon_search div:hover img { transform:scale(1.2);transition-duration:0.3s; } 
div.amazon_search div p { position:absolute;width:120px; } 
div.amazon_search div a p { bottom:28px;background-color:rgba(100,100,100,0.3);color:white;margin:1px;font-size:9pt;white-space:nowrap;text-overflow:ellipsis;overflow:hidden; }
div.amazon_search div p { bottom:0px;text-align:right;font-weight:bold;color:#cc0000;font-size:8pt;text-shadow:2px 2px 2px #808080; }
div.amazon_search footer { font-size:0.8em;text-align:right; }

まとめ

前々からAmazon謹製のウィジェットにお世話になりつつも、カテゴリの指定くらいさせて欲しいよなぁー、自分で作ろうかなぁーとは思いつつも重い腰が上がりませんでした。

しかし今回、ずいぶん長期間に渡って不具合が放置されているように感じます。ついさっき(2020年5月末)使ってみてもやはり日本語検索で文字化けしていましたし。

自作しても、本家のウィジェットが動くようになったらすぐ戻すことになるだろう、と思っていましたが、こう、長期間本家のウィジェットが使えないとなると、作っておいて良かった感があります。カテゴリ指定もできるようになりましたし。

また、自分用の備忘録のつもりでアップしたスクリプトでしたが、ありがたいことに、お使い頂いた方からのバグ報告やご要望のおかげで、コードをブラッシュアップすることが出来ました。

あぁぁ、そうそう!大事なことを忘れていました。

コードをスリムにするために外部サイトからのブロック等、エラー処理をサボっている部分がありますので、本格運用する際はPHPのコメント欄にあるとおり、アクセス元(HTTP_REFERER)のチェック処理は入れておいたほうが良いと思います。

それでは、拙いスクリプトではございますが、どこかの誰かのお役に立てれば幸いです。

『Amazonの商品検索ウィジェットが文字化けするので自作してみた part3』へのコメント

  1. 名前:Berghilo 投稿日:2020/05/29(金) 00:35:41 ID:f8177b6e4 返信

    早速のカテゴリの対応ありがとうございます。
    でも私の環境下ではカテゴリ指定ができませんでした。
    data-searchindex=”Music” や data-searchindex=”Books”
    にキャッシュを消すという data-update=”1″ を付けましたが駄目でした。Allになります。

    また、これまではファイルはどこに置いても問題なかったのが、絶対パスを指定しても、amazon_search.phpがルートに置いてあるパスに切り替わってしまいました。
    クロームの検証 < Consoleで確認しました。
    そのため、アマゾン商品掲載位置にはWordPressの404 not foundページが出てしまいました。ちょっとびっくりしました(笑)

    今はルートに置いて動いております。
    でもカテゴリは指定できていません。

  2. 名前:Berghilo 投稿日:2020/05/29(金) 09:09:05 ID:f8177b6e4 返信

    おはようございます。
    ブラウズノードはちゃんと区別してくれるので、data-searchindexからdata-browsenodeidに変えて対応しています。こちらのほうがより細かい分類ができるんですね。

    • 名前:とっちら 投稿日:2020/05/29(金) 09:18:57 ID:641b84aa7 返信

      テストありがとうございます!

      あわわ… 恥ずかしながら、またもやぼくのスペルミスで、searchindexの綴りを間違えておりました(*ノェノ)キャー
      自分が使っているスクリプトは直したのに公開版のほうを直し忘れているという…

      記事中のスペルミス、および配布しているZIP内のスペルミスも直しておきました。ご報告助かりました m(_ _)m

      • 名前:Berghilo 投稿日:2020/05/29(金) 09:50:56 ID:f8177b6e4 返信

        確認しました。
        無事searchindexもできました。
        ありがとうございます。

        さっきの私のテストサイトのアドレスが書いてあったコメントは不要ですね。削除しておいてください。

        • 名前:とっちら 投稿日:2020/05/29(金) 10:35:21 ID:641b84aa7 返信

          サンプルまで用意して頂きありがとうございました!
          言われなければずっとスペルミスに気が付かなかったと思うのでとても助かりました。

  3. 名前:匿名 投稿日:2021/01/26(火) 18:22:20 ID:3f4fddc02 返信

    今現在も、アマゾンアソシエイトの検索リンクがおかしいままです。
    どうしたものかと、検索してみたら、こちらのページを見つけまして。
    私には、こちらのページの事も、微妙な理解度で、実用できそうもないです。

    アマゾンにも、問い合わせをしてみていますが、
    1年位放置されているようでは、期待できなさそうですね。

    その場合には、こちらのようなサイトを参考にさせていただきます。
    役に立ちそうな記事の作成、今後も在ると色んな人の助けに成ると思うので、
    頑張らない程度に続けてください。

    • 名前:とっちら 投稿日:2021/01/26(火) 20:43:58 ID:14972507c 返信

      暖かいコメントありがとうございます!
      つい先日も古い記事でAmazonの検索ウィジェットで文字化けしているのを発見し、あれぇ…まだ治ってない…もしかしてうちだけなのかな…などと思いましたが、やはり皆さんもお困りだったのですね。

      PHPに対応しているレンタルサーバーならここで配布しているPHPを組み込むだけですが、慣れていない方にとっては不安かと思います。

      可能であればタグを貼るだけで使えるWebサービスにでもしたいところですが、AmazonアソシエイトのAPIはリクエスト数に上限があるためそれも難しい。

      PHP等が使えない方のためにもAmazon本家のほうで対応して頂きたいものです。

  4. 名前:まきあやや 投稿日:2021/05/08(土) 15:19:11 ID:949081123 返信

    私も文字化けで検索してこのページに辿り着きました。
    PHPは素人ですが、丸コピーしたところ、なんと動きました。
    そこで、図々しいついでに、1つ質問です、

    しばらく使っていたのですが、amazonで画像がないときの画像がおかしくなりました。
    画像が無いときの指定箇所と思い、
    if ($row_upd[‘image_s’] == ”) $row_upd[‘image_s’] = ‘httpsのアドレス’;
    のようにimage_mとimage_lも自分のサイトの画像を指定していたのですが、最近、
    https://m.media-amazon.com/images/I/01MKUOLsA5L._SL160_.gif
    が表示してしまいます。

    もし、おわかりなら教えて下さい。
    よろしくお願いします。

    • 名前:とっちら 投稿日:2021/05/08(土) 15:41:56 ID:0744b166a 返信

      おぉ… コード読みに自信がないと、誰ともわからない人間が書いたコードを貼り付けて使うのは怖かったかと思いますw
      お試し頂きありがとうございます m(_ _)m

      画像がないときの処理もそのやりかたで間違いありませんが、最近はAPI自体が01MKUOLsA5L._SL160_.gifを返してしまうのですねー。

      うぅ~ん、こればかりは
      if ($row_upd[‘image_s’] == ‘https://m.media-amazon.com/images/I/01MKUOLsA5L._SL160_.gif’) { ~ }

      というように判断するしかないかも知れませんねー。美しくないですが…。

      • 名前:まきあやや 投稿日:2021/05/09(日) 09:36:38 ID:f2a49fbca 返信

        言われたとおりにしたら最初はキャッシュのせいか直らなかったのですが、今は前のno-image画像になりました。
        ありがとうございます!! 感謝 感謝です。