javascriptとjqueryでBookmarkletを作ろうの第三回
#はじめに
前回までで、BookmarkletでjQueryを動かす下地ができたので、そこに具体的にコードを埋め込んでbookmarkletを作り上げていきます。
※このサンプルは他人さまのウェブページのHTMLをほじくり倒すので、HTMLの構造が変わってしまったら動かなくなることがあります。
#使うもの
- javascript
- jQuery3
#作るもの
楽天の商品ページから、いろんな情報を探してピックアップして表示するものを作ってみます。
##サンプルURL
https://item.rakuten.co.jp/soukaidrink/9000009984074/
クリスタルガイザー(500mL*48本入)
楽天の商品ページです。普通のjavascriptで正規表現使ってみたり、jqueryで値を引っ張ってみたりやっていますが、正解はありませんので参考程度に見てください。
##作成したbookmarklet全体
javascript:void((function(f){
// jQueryの存在チェックとバージョンチェック
if(window.jQuery && jQuery().jquery > '1.8') {
// jQueryが存在していればそれをそのまま使う
f(jQuery);
}else{
var script = document.createElement('script');
script.src = '//code.jquery.com/jquery-3.2.1.min.js';
script.onload = function(){
var $ = jQuery.noConflict(true);
f($);
};
document.body.appendChild(script);
}
})(
function($, undefined){
// バージョン確認
;;; console.log('jQuery: ', $().jquery);
//1.URLチェック
if( !location.href.match(/item.rakuten.co.jp/)){
alert('対象ページではありません');
return;
}
//2.urlから値を取る
console.log(location.pathname);
if( location.pathname.match(/\/([^\/]*)\/([^\/]*)/)){
console.log('shop url:'+RegExp.$1);
console.log('item url:'+RegExp.$2);
}
//3.formの値を取る
console.log('shop id:' +$('input[type="hidden"][name="shop_bid"]').val());
console.log('item id:' + $('input[type="hidden"][name="item_id"]').val());
//4.bodyのHTMLをテキスト処理
htmlbody = document.body.innerHTML;
if( htmlbody.match(/商品レビューを見る(([0-9,]*)件)/)){
console.log('review count:' + RegExp.$1);
}
//5.json文字列をいただく(複数行は面倒なので改行は全消し)
htmlbody = htmlbody.replace(/\n/g, '');
//schema orgのテキストを横取り
if( htmlbody.match(/<script type="application\/ld\+json">(.*?)<\/script>/)){
console.log(RegExp.$1);
schema_org = eval("(" +RegExp.$1+")");
console.log(schema_org);
console.log(schema_org['itemListElement'][0]['item']['name']);
}else{
console.log('un match');
}
//6.bookmarkletの起動を制御するコード
//初回だったらdivタグを突っ込み、2日目以降はタグの値をカウントアップ
if( $('div#executed').length ){
cnt = $('div#executed').text();
cnt ++;
console.log(cnt +'回目');
$('div#executed').text(cnt);
//2回動くのが都合が悪いなら
//return;
}else{
$('body').prepend('<div id="executed">1</div>');
}
//7.特定の要素を囲む、要素を追加する
$('span.item_name').wrap('<div id="bmlet01"></div>');
$('div#bmlet01').append('<div id="bmlet01_title">item name</div>');
//自分で追加した要素にCSS
$('div#bmlet01').css({'border':'solid'});
$('div#bmlet01_title').css({'background-color':'red','color':'white'});
//8.ページ画像のON/OFF
$('img').toggle();
//画像を全てOFF
//$('img').hidden();
}
)
);
コードの解説をしていきます。
###解説1
//1.URLチェック
if( !location.href.match(/item.rakuten.co.jp/)){
alert('対象ページではありません');
return;
}
表示しているURLがbookmarkletの対象としているか確認をします。正規表現で確認しています。対象でない場合にはreturnしてしまいましょう。後続の処理は動きません。
###解説2
if( location.pathname.match(/\/([^\/]*)\/([^\/]*)/)){
console.log('shop url:'+RegExp.$1);
console.log('item url:'+RegExp.$2);
}
楽天のURLの後半部分には、店のIDと商品のIDが埋め込まれているので、これを正規表現で刈り取っています。エスケープ文字があるので読みにくいですが、先頭がスラッシュ、スラッシュ以外の繰り返し、スラッシュ1回、スラッシュ以外の繰り返し、という意味です。
###解説3
//3.formの値を取る
console.log('shop id:' +$('input[type="hidden"][name="shop_bid"]').val());
console.log('item id:' + $('input[type="hidden"][name="item_id"]').val());
フォームの内容は、jQueryを使うととっても簡単に参照できます。hiddenでも楽ちん。IDで参照しない場合はフォームの部品が複数取れてしまうかもしれません。
###解説4
//4.bodyのHTMLをテキスト処理
htmlbody = document.body.innerHTML;
if( htmlbody.match(/商品レビューを見る(([0-9,]*)件)/)){
console.log('review count:' + RegExp.$1);
}
次は、bodyのHTML全体から何かを探すサンプルです。今回はレビューの件数を正規表現で取り出しています。「レビューを見る(000件)」という部分をちょっとでも返られたらアウトです。
###解説5
//5.json文字列をいただく(複数行は面倒なので改行は全消し)
htmlbody = htmlbody.replace(/\n/g, '');
//schema orgのテキストを横取り
if( htmlbody.match(/<script type="application\/ld\+json">(.*?)<\/script>/)){
console.log(RegExp.$1);
schema_org = eval("(" +RegExp.$1+")");
console.log(schema_org);
console.log(schema_org['itemListElement'][0]['item']['name']);
}else{
console.log('un match');
}
これも上の4と同じく、HTML全体から文字列の抜き出しなのですが、複数行の文字列の場合は正規表現が面倒なので取り出す前に改行を全部置き換えています。正規表現でマッチした部分(の間の文字列)がjsonの文字列なので、evalしてオブジェクト化しています。オブジェクト化した変数は、配列構造になっているのでこんな感じで参照可能です。
###解説6
//6.bookmarkletの起動を制御するコード
//初回だったらdivタグを突っ込み、2日目以降はタグの値をカウントアップ
if( $('div#executed').length ){
cnt = $('div#executed').text();
cnt ++;
console.log(cnt +'回目');
$('div#executed').text(cnt);
//2回動くのが都合が悪いなら
//return;
}else{
$('body').prepend('<div id="executed">1</div>');
}
このコードは、bookmarkletが2回以上動かないように制御するためのものです。Bodyのすぐ下に勝手に<div>
タグを忍び込ませ、カウントを数えています。jQueryが使えるとこの辺のコードも簡単です。<div>
のidが既存のidと被らないように適当に変えてください。2重起動を防止するのであれば、URLチェックの後に動かすのがいいでしょう。
###解説7
//7.特定の要素を囲む、要素を追加する
$('span.item_name').wrap('<div id="bmlet01"></div>');
$('div#bmlet01').append('<div id="bmlet01_title">item name</div>');
//自分で追加した要素にCSS
$('div#bmlet01').css({'border':'solid'});
$('div#bmlet01_title').css({'background-color':'red','color':'white'});
このコードは、HTMLのパーツを分かりやすくするためのサンプルです。タグ、ID、クラス名あたりで名指しして<div>
で囲って目立たせています。jQuery使うと簡単です。
もともとのHTMLを汚染しますので、何度も実行するとどんどん汚くなります。
###解説8
//8.ページ画像のON/OFF
$('img').toggle();
//画像を全てOFF
//$('img').hidden();
楽天の商品ページには縦に長い画像が多いですからね、、全部OFFするならこんな感じです。特定の要素の下の画像だけ非表示にするとか、jQueryのセレクタを書き換えれば自由にできるはずです。
#まとめ
bookmarkletとjQueryを使うとページ内に埋め込まれた値を抜き出したり、要素を強調したり、不要なところを隠したりということが簡単にできます。受け取ったHTMLだけで何かするトリックはこれくらいでしょうか。本番にデプロイするコードには不要だけど、開発中やリリース後にデバッグ用にあったら便利なものは、bookmarklet化して配っておくのはいかがでしょう。
このページの商品コードって何だっけ?みたいな作業って、何度も発生しませんか?bookmarkletにして一発で探せるようにしておくと作業効率が上がります。
次回は、ページ内にある要素を抜き出した後にajaxで非同期通信するサンプルを作ってみます。