ときどきプログラミング

プログラミングとかで遊んで面白かったことをシェアするブログ

Amazonで本を検索すると同時に、喜久屋書店にも在庫があるかを確認できるChromeエクステンションをjQueryで作った

※更新 ver1.0.4 喜久屋書店の仕様変更で上手く表示されてなかったので修正 2015/03/01 14:49

Amazonで本を検索したときに、喜久屋書店に在庫があるかどうかを そのページ内にシームレスで表示するChromeエクステンションです。

f:id:kurashiki8bit:20140424102337p:plain

その本、図書館にあります。にインスパイアされています。

主にjQueryで制作しました。

jQueryで作ると、とても簡単なコードだけで出来ました。 面白かったのでソースも公開します。 改変自由なので、あなたも「その本、〇〇にあります。」を作ってみてください。

ダウンロード&インストール

Chromeウェブストアで配布しています。

その本、喜久屋書店にあります。(Chromeウェブストア)

ソースコード

ダウンロード(zipファイル)

下記の6つのファイルで構成されています。

  • manifest.json
  • main.js
  • options.html
  • options.js
  • background.js
  • jquery.min.js (version 1.11.0)

manifest.json

Chromeエクステンションは、マニフェストファイルと呼ばれるJSONフォーマットのファイルを manifest.json という名前で持つ必要があるらしい。ここにエクステンションの情報とかを定義するみたい。 permissionsの http://61.120.69.13/* は、喜久屋書店のサーバIPへの問い合わせアクセスを許すという意味。 content_scriptsのmatchesが動作対象のURL。ここではAmazonの検索後のページでのみ動くように指定。

{
  "name": "その本、喜久屋書店にあります。",
  "version": "1.0.3",
  "manifest_version": 2,
  "description": "その本、喜久屋書店にあります。",
  "permissions": [
    "http://61.120.69.13/*"
  ],
  "content_scripts": [
    {
      "matches": [
        "http://www.amazon.co.jp/*dp/*",
        "http://www.amazon.co.jp/gp/product/*"
      ],
      "js": ["jquery.min.js","main.js"],
      "run_at": "document_start"
    }
  ],
  "background": {
    "scripts": ["background.js"]
  },
  "options_page": "options.html"
}

main.js

一番のメイン部分。Amazonページ内にISBNがあった場合、その値を取得して、$.ajax喜久屋書店の検索CGIにGETで問い合わせに行く。返ってきた値(ページ全体)に店舗名が入っていれば在庫ありと判断して、その結果をAmazonのページ内に追記(afterやbefore)する。

始めの、chrome.runtime.sendMessageは、オプションページで設定した店舗名(loadStorageの値)をbackground.js経由でshop変数に入れています。ここだけ分かりにくいですが、こうしないと取得できなかったのでこうしてます。

$(function(){
    var shop = "";
    chrome.runtime.sendMessage({}, function(response) { // オプションページの設定(localStorageの値)をshop変数に入れる
        shop = response.shop;
    });
    $("li").each(function(){
        if($(this).html().match(/ISBN-13/)){
            var matches = $(this).html().match(/^<b>(ISBN-13):<\/b> (.+)$/); // AmazonからISBNを取得
            var isbn13 = matches[2].replace("-","");
            var url = "http://61.120.69.13/k_detail.jsp"; // 喜久屋書店側の検索CGI
            $.ajax({
                type: "GET",
                dataType: "html",
                url: url,
                data: { "ISBN":isbn13, "VIEW":"word", "ARGS":isbn13 },
                beforeSend: function(xhr){ xhr.overrideMimeType("text/html;charset=Shift_JIS"); } // アクセス先ページはShift_JIS
            })
            .done(function(data){
                var title = "<font color=chocolate>この本が喜久屋書店にあるか検索</font> → ";

                if(shop=="全店") { 
                    var pattern = new RegExp("喜久屋書店 ");
                } else {
                    var pattern = new RegExp("喜久屋書店 "+shop);
                } 

                if(data.match(pattern)) { // 検索結果を調べる
                    var ans = "喜久屋書店("+shop+") 在庫あり";
                    var color = "#009900"; // 緑
                }
                else{
                    var ans = "喜久屋書店("+shop+") 在庫なし";
                    var color = "#990000"; // 赤
                }

                // Amazonに追記するhtmlタグを作る
                var html = title+"<a style=\"color:"+color+"\" target=\"new\" href=\""+url+"?ISBN="+isbn13+"&VIEW=word&ARGS="+isbn13+"\"><b>"+ans+"</b></a>";
                if($("div#dynamicDeliveryMessage_feature_div").length) {
                    $("div#dynamicDeliveryMessage_feature_div").before(html);
                }
            });
        }
    });
});

options.html

喜久屋書店には複数の店舗があるので、検索対象の店舗をユーザがオプションで設定できるようにと作りました。ただのhtmlですね、とても簡単。

<html>
<head>
<meta charset="utf-8"/>
<title>その本、喜久屋書店にあります。</title>
<script src="options.js"></script>
</head>
<body>
その本、喜久屋書店にあります。<br>
<br>
店舗を指定して下さい。<br>
<br>
喜久屋書店
<select name="shop" id="shop">
<option value="全店">全店</option>
<option value="小樽店">小樽店</option>
<option value="漫画館仙台店">漫画館仙台店</option>
<option value="宇都宮店">宇都宮店</option>
<option value="太田店">太田店</option>
<option value="千葉ニュータウン店">千葉ニュータウン店</option>
<option value="高岡店">高岡店</option>
<option value="大垣店">大垣店</option>
<option value="草津店">草津店</option>
<option value="漫画館京都店">漫画館京都店</option>
<option value="阿倍野店">阿倍野店</option>
<option value="東急ハンズ心斎橋店">東急ハンズ心斎橋店</option>
<option value="寝屋川店">寝屋川店</option>
<option value="奈良駅店">奈良駅店</option>
<option value="橿原店">橿原店</option>
<option value="大和郡山店">大和郡山店</option>
<option value="北神戸店">北神戸店</option>
<option value="神戸北町店">神戸北町店</option>
<option value="東急プラザ新長田店">東急プラザ新長田店</option>
<option value="神戸学園都市店">神戸学園都市店</option>
<option value="西神中央店">西神中央店</option>
<option value="明石駅ビル店">明石駅ビル店</option>
<option value="豊岡店">豊岡店</option>
<option value="倉敷店">倉敷店</option>
<option value="小倉店">小倉店</option>
<option value="熊本店">熊本店</option>
</select>

<button id="save">保存</button>

</body>
</html>

options.js

オプションページで保存ボタンが押された場合、localStorageに店舗の値を保存しています。数行のJavaScriptだけです。

function $(id){
    return document.getElementById(id);
}
function init(){
    if(!localStorage.shop) {
        localStorage.shop = "全店"; // デフォルト値
    }
    $("shop").value = localStorage.shop;
}
function save(){
    localStorage.shop = $("shop").value;
    alert("店舗を"+localStorage.shop+"に変更しました。");
}
window.onload=function(){
    init();
    $('save').onclick=save;
}

background.js

main.jsで直にlocalStorage.shopと書いても(amazon.co.jplocalhostドメインが違うから?)データが取得できなかったので、background.js経由で間接的にlocalStorageの値を取得するようにしました。

chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
    var shop = localStorage.shop;
    if(!shop) { shop = "全店"; } // デフォルト値
    sendResponse({shop:shop});
});

あとがき

そもそも、自分だけで使うのであれば、店舗をそのままmain.jsに書けばよいので、オプションページ関連(option.html,option.js,background.js)はいらないし、main.jsはもっとシンプルになります。利便性のため追加しているだけなので、この辺を抜きにして考えてもらうとjQueryChromeエクステンションが非常に簡単に作れていることが分かると思います。

参考

jQuery を使って 30 分で Chrome 拡張を作ってみた

jQueryデザインブック 仕事で絶対に使うプロのテクニック

jQueryデザインブック 仕事で絶対に使うプロのテクニック