Amazon+価格COM 別版

id:otn:20090426 で書いた件で何をやっていたかというと、id:gigi-net:20090418:1240066430 で発表されたすごいアイデアAmazonで閲覧中の商品に価格comから最低価格を取ってきて付加するGreasemonkeyスクリプト」を自分でも書いてみようと言うことです。最初に書いたのはこの日(4/18)でしたけど、すでに本家がバージョンアップしてて(id:gigi-net:20090421:1240324155)、もう今更公開する意味はないかもしれないけど、せっかく書いたので公開しておきます。アイデアだけもらって独自コードです。


違いは、多分これくらい。
・商品ページかどうかはURLパターンで判断
・型番がない場合は商品名で検索
・最低価格以外にメーカー名:商品名も出すので、誤検索の場合にそれとわかる
・価格差は出さない
・見つからない場合は何も出さない


インストールはこちら⇒ http://homepage3.nifty.com/otn/amazonkakakucom.user.js


4/26で書いたように、Firefoxの場合は先にdocumentにappendしておけばtrのinnerHTMLにタグが書けるんだけど、appendより先にinnerHTMLをセットすると駄目というのが怪しいので、それはしないことにしました。


あと、価格欄の上に追加しようとしたら、なんと同じ id=priceBlock を持つdivが複数あるorz Amazonさん、非道いです。HTMLの基本ですよ。
しかも、見た限りでは2パターンある。
・priceBlockをそれぞれ含むpriceBlockTwister系が3つあり、そのうちpriceBlockTwisterだけがvisibleの場合
・priceBlockTwisterが無くてpriceBlockが1つだけの場合


課題としては、
・商品ページのURLがこの2パターンで過不足無いか
・priceBlockまわりで他のパターンが無いか
・検索で見つからないときの適当なキーワードでのリカバリを考える・・・労力に見合うかどうか。多分しない
・誤検索を検知してなんとかリカバリする・・・ここまでする気は全くない

4/29追記

priceBlockTwisterの部分はマウスの動きで動的に書き換わることに気づいた。つまり、この中を書き換えてもマウスを動かすと消えてしまう。しょうがないので、テーブルの中に入れるのはあきらめて、その外に付けることにする。結果としてtrの追加じゃなくてdivの追加になり、直接innerHTMLを書き換えられるので簡単になった。テーブルじゃないのでコロンの横位置がずれるかと思ったけど、そうでもないので良かった。
下記はその変更版v1.1です。

// ==UserScript==
// @name           amazonkakakucom
// @version        1.1
// @namespace      http://d.hatena.ne.jp/otn/
// @description    Amazon+価格COM最安値
// @include        http://www.amazon.co.jp/*/dp/*
// @include        http://www.amazon.co.jp/gp/product/*
// ==/UserScript==
// http://homepage3.nifty.com/otn/amazonkakakucom.user.js
var key, proDiv, bTags, title;
// メーカー型番が書いてあればそれを
if((proDiv=document.getElementById("productDetailsDiv")) && (bTags=proDiv.getElementsByTagName("b"))){
	for(var i=0; i<bTags.length; ++i){
		if(bTags[i].textContent.substr(0,6)=="メーカー型番"){
			key=bTags[i].nextSibling.textContent;
			break;
		}
	}
}
// 書いてなければ商品タイトルを検索に使う
if(!key){
	if(title=document.getElementById("btAsinTitle")){
		key=title.textContent;
	}
}
if(key){
	GM_xmlhttpRequest({
		method:"GET", 
		url:"http://api.kakaku.com/Ver1.1/ItemSearch.aspx?SortOrder=pricerank"+
			"&Keyword="+encodeURIComponent(key),
		onload:doit
	});
}

function doit(resp){
	var root=document.createElement("div");
	root.innerHTML=resp.responseText;
	var priceTags=root.getElementsByTagName("LowestPrice");
	if(priceTags.length>0){
		var price=priceTags[0].textContent, wk;
		while(wk=price.replace(/([0-9]+)([0-9]{3})/,"$1,$2"), price!=wk) price=wk;
		var linkUrl=root.getElementsByTagName("ItemPageUrl")[0].textContent;
		var maker  =root.getElementsByTagName("MakerName"  )[0].textContent;
		var product=root.getElementsByTagName("ProductName")[0].textContent;
		var priceBlock=document.getElementById("priceBlock");
		var here;
		while(here=priceBlock.parentNode, here.nodeName!="TD") priceBlock=here;
		var div=document.createElement("div");
		div.innerHTML='<span class="priceBlockLabel">価格COM:</span>'+
		'<span><b class="priceLarge">¥'+price+'</b>'+
		'&nbsp;&nbsp;(<a href="'+linkUrl+'">'+maker+':'+product+'</a>)</span>';
		here.insertBefore(div,priceBlock);
	}
}


P.S.
本家改良版に書いてある金額へのカンマ付加のコード

while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));

参照元をたぐっていくと、最後はアダルトなページにww
JavaScriptで、演算子の左項が右項に先立って評価されるというのは言語仕様に書いてあるのだろうか?調べてないけど。