blog/content/post/2008-02-09-00000792.md

377 lines
29 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 図書館を検索するGreasemonkeyの作り方
author: kazu634
date: 2008-02-09
url: /2008/02/09/_848/
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3707;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- つれづれ
---
<div class="section">
<p>
 つい最近<a href="http://www.library.pref.miyagi.jp/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.library.pref.miyagi.jp/', '宮城県立図書館');" target="_blank">宮城県立図書館</a>がリニュアールされた。その結果、Amazonの個別ページを開いた際に図書館の蔵書チェックを行うGreasemonkeyスクリプトがうまく動かなくなってしまった。大学で借りれるものならば借りたい<a href="http://www.library.pref.miyagi.jp/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.library.pref.miyagi.jp/', '宮城県立図書館');" target="_blank">宮城県立図書館</a>に行けば借りられるのなら借りたいのだ!
</p>
<p>
 何を言っているかわからない人は下の画像を見てほしい。
</p>
<p>
<center>
<a href="http://f.hatena.ne.jp/sirocco634/20080209105045" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://f.hatena.ne.jp/sirocco634/20080209105045', '');" class="hatena-fotolife" target="_blank"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/s/sirocco634/20080209/20080209105045.jpg" alt="f:id:sirocco634:20080209105045j:image" title="f:id:sirocco634:20080209105045j:image" class="hatena-fotolife" /></a>
</center>
</p>
<p>
こんな形で左上に<a href="http://www.library.tohoku.ac.jp/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.library.tohoku.ac.jp/', '東北大学附属図書館');" target="_blank">東北大学附属図書館</a>に蔵書があればリンクが表示される。右下には実験用に作った<a href="http://www.klnet.pref.kanagawa.jp/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.klnet.pref.kanagawa.jp/', '神奈川県立図書館');" target="_blank">神奈川県立図書館</a>の蔵書検索スクリプトの結果<span class="footnote"><a href="/sirocco634/#f1" name="fn1" title="今回は関係ないけど、左下には各種オンラインストアへのリンクが表示されるようになっている">*1</a></span>
</p>
<p>
 今回、<a href="http://www.library.pref.miyagi.jp/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.library.pref.miyagi.jp/', '宮城県立図書館');" target="_blank">宮城県立図書館</a>の蔵書検索Greasemonkeyを作り直そうとしたのだが、自分の作業過程をかなり忘れていたことに気づいたので、自分用の備忘録としてここに書き散らかしておきます。ちなみに<a href="http://www.library.pref.miyagi.jp/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.library.pref.miyagi.jp/', '宮城県立図書館');" target="_blank">宮城県立図書館</a>用のスクリプトはどうやらGreasemonkeyの仕様のためにうまく動かないことが判明。。。refererを指定してpostできないみたいなんです。ぐすん。
</p>
<p>
 ちなみに私はGreasemonkeyやJavascriptについてあまり詳しく知らないので、おかしなことを書いている可能性は高いです。そこら辺を割り引いて読んでください
</p>
<p>
<a name="seemore"></a>
</p>
<h4>
先人の肩に乗っていこう!
</h4>
<p>
 Googleなんかで検索すると色々と提供している人が多いことに気づきます。「<a href="http://d.hatena.ne.jp/myrmecoleon/20070627/1182958284" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/myrmecoleon/20070627/1182958284', 'GreasemonkeyでAmazonから探せる図書館まとめ &#8211; Myrmecoleon in Paradoxical Library. はてな新館');" target="_blank">GreasemonkeyでAmazonから探せる図書館まとめ &#8211; Myrmecoleon in Paradoxical Library. はてな新館</a>」でまとめられています。それらのGreasmeonkeyスクリプトを眺めていると、二つの種類があることに気づきます。
</p>
<ol>
<li>
検索結果のページに飛ばすリンクを作成するタイプ
</li>
<li>
検索結果のページを解析して、蔵書があれば個別の蔵書ページへのリンクを作成するタイプ
</li>
</ol>
<p>
こんな感じです。今回は二つめのタイプに取りかかることにします。
</p>
<p>
 私は素人さんなので、既存のスクリプトを変更することで自分のやりたいことを実現することにしました。こういうときはじゃんじゃん先人の肩に乗っていけばいいと思います。
</p>
<h4>
参考にしたスクリプト
</h4>
<p>
 自分が過去に作ったのを見よう見まねで色々と修正をしてみることにした。とりあえず見つけたのはこいつだった。
</p>
<pre class="syntax-highlight">
<span class="synComment">// ==UserScript==</span>
<span class="synComment">// @name Amazon2</span>
<span class="synComment">// @namespace </span>
<span class="synComment">// @description Temporary Script.</span>
<span class="synComment">// @include http://*.amazon.*</span>
<span class="synComment">// ==/UserScript==</span>
<span class="synComment">// HTMLでなければ終了</span>
<span class="synStatement">if</span>(<span class="synStatement">document</span>.contentType != <span class="synConstant">'text/html'</span>) <span class="synStatement">return</span>;
<span class="synComment">// ASINを見つけるよ</span>
<span class="synStatement">document</span>.body.parentNode.innerHTML.match(<span class="synConstant">/name=\&#34;ASIN\&#34; value=\&#34;([0-9A-Z]{10})([\/\-_a-zA-Z0-9]*)/i</span>);
<span class="synComment">// ASINが見つからなければ終了</span>
<span class="synStatement">if</span> (<span class="synType">RegExp</span>.$1 == <span class="synConstant">''</span>) <span class="synStatement">return</span>;
<span class="synComment">// asinを変数に代入</span>
<span class="synIdentifier">var</span> asin = <span class="synType">RegExp</span>.$1;
<span class="synComment">// パネルの設定</span>
<span class="synIdentifier">var</span> GM_infoPanel = <span class="synStatement">document</span>.createElement(<span class="synConstant">'div'</span>)
<span class="synStatement">with</span>(GM_infoPanel.style) <span class="synIdentifier">{</span>
bottom = 0;
right = 0;
padding = <span class="synConstant">'2px'</span>;
opacity = 0.8;
fontsize = <span class="synConstant">'x-small'</span>;
color = <span class="synConstant">'#000000'</span>;
backgroundColor = <span class="synConstant">'#EEEEEE'</span>;
border = <span class="synConstant">'1px solid #C0C0C0'</span>;
zIndex = 100;
position = <span class="synConstant">'fixed'</span>;
<span class="synIdentifier">}</span>
GM_infoPanel.innerHTML = <span class="synConstant">&#34;Library Searching...&#34;</span>;
GM_xmlhttpRequest(<span class="synIdentifier">{</span>
method : <span class="synConstant">&#34;POST&#34;</span>,
url : <span class="synConstant">&#34;http://www.klnet.pref.kanagawa.jp/opac/OPP1400&#34;</span>,
data : <span class="synConstant">&#34;TERM=INDEX-1&#38;WORD=&#34;</span> + asin + <span class="synConstant">&#34;&#38;SP_SEARCH=1&#38;MENUNO=0&#34;</span>,
headers: <span class="synIdentifier">{</span><span class="synConstant">'User-Agent'</span>: <span class="synConstant">'Mozilla/4.0 (compatible)'</span>,
<span class="synConstant">'Content-type'</span>: <span class="synConstant">'application/x-www-form-urlencoded'</span>,
<span class="synConstant">'Host'</span>: <span class="synConstant">'www.klnet.pref.kanagawa.jp'</span><span class="synIdentifier">}</span>,
onload : <span class="synIdentifier">function</span>(response)<span class="synIdentifier">{</span>
<span class="synStatement">if</span> (response.responseText.match(<span class="synConstant">/OPP1500[^&#34;]*/i</span>)) <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> result=response.responseText.match(<span class="synConstant">/OPP1500[^&#34;]*/g</span>);
comment = <span class="synConstant">'http://www.klnet.pref.kanagawa.jp/opac/'</span> + result<span class="synIdentifier">[</span><span class="synIdentifier">]</span>;
GM_infoPanel.innerHTML += <span class="synConstant">'&#60;br&#62;&#60;a href=&#34;'</span> + comment + <span class="synConstant">'&#34; target=&#34;blank&#34;&#62;Kanagawa Pref&#60;/a&#62;'</span>;
<span class="synIdentifier">}</span>
<span class="synStatement">else</span><span class="synIdentifier">{</span>
GM_infoPanel.innerHTML += <span class="synConstant">'&#60;br&#62;Kanagawa Pref: Not Found'</span>;
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>
<span class="synIdentifier">}</span>);
<span class="synComment">// パネルの表示</span>
<span class="synStatement">document</span>.body.appendChild(GM_infoPanel);
</pre>
<p>
こいつの読み方を見ていく。
</p>
<h4>
スクリプトの読み方
</h4>
<p>
 順を追って見ていくことにします。まず冒頭の
</p>
<pre class="syntax-highlight">
<span class="synComment">// ==UserScript==</span>
<span class="synComment">// @name Amazon2</span>
<span class="synComment">// @namespace </span>
<span class="synComment">// @description Temporary Script.</span>
<span class="synComment">// @include http://*.amazon.*</span>
<span class="synComment">// ==/UserScript==</span>
</pre>
<p>
はお約束なので、とりあえず書いておくべき部分。「@include」の部分は「<a href="http://*.amazon.co.jp" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://*.amazon.co.jp', 'http://*.amazon.co.jp');" target="_blank">http://*.amazon.co.jp</a>」になっていることが多いのだけれど、自分の場合Amazon.comから海外の古本屋サイトに行くなどの用途も考慮しているのでjpだけに決めうちしていません。ここらへんは使い回しているので、各自で適当に書き換えればいいかと。
</p>
<p>
 次の
</p>
<pre class="syntax-highlight">
<span class="synComment">// HTMLでなければ終了</span>
<span class="synStatement">if</span>(<span class="synStatement">document</span>.contentType != <span class="synConstant">'text/html'</span>) <span class="synStatement">return</span>;
<span class="synComment">// ASINを見つけるよ</span>
<span class="synStatement">document</span>.body.parentNode.innerHTML.match(<span class="synConstant">/name=\&#34;ASIN\&#34; value=\&#34;([0-9A-Z]{10})([\/\-_a-zA-Z0-9]*)/i</span>);
<span class="synComment">// ASINが見つからなければ終了</span>
<span class="synStatement">if</span> (<span class="synType">RegExp</span>.$1 == <span class="synConstant">''</span>) <span class="synStatement">return</span>;
<span class="synComment">// asinを変数に代入</span>
<span class="synIdentifier">var</span> asin = <span class="synType">RegExp</span>.$1;
</pre>
<p>
という部分はAmazonの個別ページに現在いるのかどうかをチェックしている部分。個別ページでなければ、処理を進めずに終了させている。これはAmazonの個別ページにはかならず
</p>
<pre class="syntax-highlight">
<span class="synIdentifier">&#60;</span><span class="synStatement">input</span><span class="synIdentifier"> </span><span class="synType">type</span><span class="synIdentifier">=</span><span class="synConstant">&#34;hidden&#34;</span><span class="synIdentifier"> </span><span class="synType">name</span><span class="synIdentifier">=</span><span class="synConstant">&#34;ASIN&#34;</span><span class="synIdentifier"> </span><span class="synType">value</span><span class="synIdentifier">=</span><span class="synConstant">&#34;4797336803&#34;</span><span class="synIdentifier"> /&#62;</span>
</pre>
<p>
という一行があること利用しています。ちなみにasinというのはisbn10と同じ。すべての本は固有な10桁の番号が割り振られていて、その番号のことをisbn10といいます。isbn10は必ず「10桁の数字」、もしくは「9桁の数字 + X」になります。isbn10がわかればどんな図書館でも蔵書検索できるので、「asinが存在するか調べる」ことは、「蔵書検索ができるか」をチェックしていることになります。<span class="footnote"><a href="/sirocco634/#f2" name="fn2" title="ハードカバーと文庫版は異なるisbnが振られていることに注意。また、雑誌や雑貨などにもasinは割り振られているのですが、それらにはisbn10が割り振られていないのでAmazon側で適当な値を割り振っています。一応、そいつも認識するようにしています。こいつはアフィリエート作成のために取っておいたんだけど、はてなに移ってからは使ってないな(..;) ">*2</a></span>asinは後で必要になるので、変数asinに代入しています。
</p>
<p>
 次はパネルの設定。
</p>
<pre class="syntax-highlight">
<span class="synComment">// パネルの設定</span>
<span class="synIdentifier">var</span> GM_infoPanel = <span class="synStatement">document</span>.createElement(<span class="synConstant">'div'</span>)
<span class="synStatement">with</span>(GM_infoPanel.style) <span class="synIdentifier">{</span>
bottom = 0;
right = 0;
padding = <span class="synConstant">'2px'</span>;
opacity = 0.8;
fontsize = <span class="synConstant">'x-small'</span>;
color = <span class="synConstant">'#000000'</span>;
backgroundColor = <span class="synConstant">'#EEEEEE'</span>;
border = <span class="synConstant">'1px solid #C0C0C0'</span>;
zIndex = 100;
position = <span class="synConstant">'fixed'</span>;
<span class="synIdentifier">}</span>
GM_infoPanel.innerHTML = <span class="synConstant">&#34;Library Searching...&#34;</span>;
<span class="synComment">// &#60;=== 途中省略 ===&#62;</span>
<span class="synComment">// パネルの表示</span>
<span class="synStatement">document</span>.body.appendChild(GM_infoPanel);
</pre>
<p>
ここは検索した結果を表示する部分を担当している。お呪いだと思っておいて、後で必要になれば調べると良いのではないかと思う。<span class="footnote"><a href="/sirocco634/#f3" name="fn3" title="→[google:GM_infoPanel Greasemonkey]しても自分のブログしか出てこないorz。『[asin:4798015350:title]』を参照するのが良いかも。">*3</a></span>
</p>
<h4>
検索結果を表示するURLにはサイトによって二つのパターンがある…ようだ
</h4>
<p>
 こいつが一番の山場。自分もうまく理解していないけど、オンライン書店などで検索した結果を表示する時に検索結果を表示するページのURLには二つのパターンがある。
</p>
<ol>
<li>
検索結果のページに、おのおの検索条件に対応する固有のURLが与えられているパターン
</li>
<li>
検索結果のページが常に同じURLになる。つまり、内部的に検索条件を処理しているので、決まり切ったURLに移動するパターン
</li>
</ol>
<p>
です。この二つがどのように違うのかはわからないorzのですが、とにかく二つのパターンがあります。例えば<a href="http://www.honya-town.co.jp/hst/HT/index.html" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.honya-town.co.jp/hst/HT/index.html', 'オンライン書店 本やタウン');" target="_blank">オンライン書店 本やタウン</a>でisbnが「4798015350」で調べると、検索結果のページのURLは<a href="http://www.honya-town.co.jp/hst/HTdispatch?free=&free_andor=0&title=&title_andor=0&title_title=1&title_subtitle=1&title_series=1&title_original=1&author=&author_list=0&publisher=&date_yy_from=&date_mm_from=&date_yy_to=&date_mm_to=&vague_search=1&list_kensu=20&stamp_style=0&price_from=&price_to=&isbn_cd=4798015350&pub_stat=2&submit.x=78&submit.y=10&nips_cd=" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.honya-town.co.jp/hst/HTdispatch?free=&free_andor=0&title=&title_andor=0&title_title=1&title_subtitle=1&title_series=1&title_original=1&author=&author_list=0&publisher=&date_yy_from=&date_mm_from=&date_yy_to=&date_mm_to=&vague_search=1&list_kensu=20&stamp_style=0&price_from=&price_to=&isbn_cd=4798015350&pub_stat=2&submit.x=78&submit.y=10&nips_cd=', 'こんなURL');" target="_blank">こんなURL</a>になります。だから、一番目のパターンの時はこのURLの「isbn_cd=4798015350」の部分を任意のisbnにすれば、検索結果がわかるのです。
</p>
<p>
 それに対して二つめのパターンだと、例えば<a href="http://www.klnet.pref.kanagawa.jp/opac/index.jsp" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.klnet.pref.kanagawa.jp/opac/index.jsp', '神奈川県立図書館');" target="_blank">神奈川県立図書館</a>で同じ条件で検索すると、検索結果のURLは常に「<a href="http://www.klnet.pref.kanagawa.jp/opac/index.jsp" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.klnet.pref.kanagawa.jp/opac/index.jsp', 'http://www.klnet.pref.kanagawa.jp/opac/index.jsp');" target="_blank">http://www.klnet.pref.kanagawa.jp/opac/index.jsp</a>」です。内部的にゴニョゴニョしているので、Greasemonkeyを使ってそのゴニョゴニョをしてくれるように図書館のページにお願いしてあげないといけません。そうするための命令が、「GM_xmlhttpRequest」なのです。図書館の蔵書検索の場合だと、二つめのパターンしかこれまで見たことがないです。
</p>
<h4>
<a href="http://diveintogreasemonkey.org/api/gm_xmlhttprequest.html" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://diveintogreasemonkey.org/api/gm_xmlhttprequest.html', 'GM_xmlhttpRequest');" target="_blank">GM_xmlhttpRequest</a>
</h4>
<p>
 参考にすべきは「<a href="http://diveintogreasemonkey.org/api/gm_xmlhttprequest.html" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://diveintogreasemonkey.org/api/gm_xmlhttprequest.html', 'GM_xmlhttpRequest');" target="_blank">GM_xmlhttpRequest</a>」です。今回、こんな風に用いています。
</p>
<pre class="syntax-highlight">
GM_xmlhttpRequest(<span class="synIdentifier">{</span>
method : リクエストの種類大半はpost,
url : <span class="synConstant">&#34;URL&#34;</span>,
data : <span class="synConstant">&#34;送信するデータ&#34;</span>
headers: <span class="synIdentifier">{</span><span class="synConstant">'User-Agent'</span>: <span class="synConstant">'Mozilla/4.0 (compatible)'</span>,
<span class="synConstant">'Content-type'</span>: <span class="synConstant">'application/x-www-form-urlencoded'</span><span class="synIdentifier">}</span>,
onload : <span class="synIdentifier">function</span>(response)<span class="synIdentifier">{</span>成功したときの処理<span class="synIdentifier">}</span>
</pre>
<p>
リクエストの種類は図書館の蔵書検索のページ(例は「<a href="http://www.klnet.pref.kanagawa.jp/opac/index.jsp" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.klnet.pref.kanagawa.jp/opac/index.jsp', '神奈川県立図書館 ');" target="_blank">神奈川県立図書館 </a>」)の検索用フォームの設定を見ればわかります。この場合、
</p>
<pre class="syntax-highlight">
<span class="synIdentifier">&#60;</span><span class="synStatement">FORM</span><span class="synIdentifier"> </span><span class="synType">NAME</span><span class="synIdentifier">=</span><span class="synConstant">&#34;SIMPLE&#34;</span><span class="synIdentifier"> </span><span class="synType">ACTION</span><span class="synIdentifier">=</span><span class="synConstant">&#34;OPP1400&#34;</span><span class="synIdentifier"> </span><span class="synType">METHOD</span><span class="synIdentifier">=</span><span class="synConstant">&#34;POST&#34;</span><span class="synIdentifier">&#62;</span>
</pre>
<p>
とあるのでリクエストの種類は「POST」になります。
</p>
<p>
 送信するデータは「value = &#8220;***&#8221;」となっている部分を逐一拾っていけば大丈夫なのですが、いちいちそんなことやってられないのでずるをします。<a href="https://addons.mozilla.org/ja/firefox/addon/3829" onclick="__gaTracker('send', 'event', 'outbound-article', 'https://addons.mozilla.org/ja/firefox/addon/3829', 'Live HTTP Headers');" target="_blank">Live HTTP Headers</a>を用います(<a href="http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/030livehttp.html" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/030livehttp.html', '解説');" target="_blank">解説</a>。こいつを使うとどんなデータを送っているのかが一発でわかるので便利です。Windowsなら<a href="http://www.fiddlertool.com/fiddler/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.fiddlertool.com/fiddler/', 'Fiddler');" target="_blank">Fiddler</a>というのがあります。こいつを使うと、任意のURLに任意のデータをPOSTできちゃったりして、結果を確認できます。こいつも便利です。
</p>
<p>
 こうした一連の過程を経ると、
</p>
<pre class="syntax-highlight">
GM_xmlhttpRequest(<span class="synIdentifier">{</span>
method : <span class="synConstant">&#34;POST&#34;</span>,
url : <span class="synConstant">&#34;http://www.klnet.pref.kanagawa.jp/opac/OPP1400&#34;</span>,
data : <span class="synConstant">&#34;TERM=INDEX-1&#38;WORD=&#34;</span> + asin + <span class="synConstant">&#34;&#38;SP_SEARCH=1&#38;MENUNO=0&#34;</span>,
headers: <span class="synIdentifier">{</span><span class="synConstant">'User-Agent'</span>: <span class="synConstant">'Mozilla/4.0 (compatible)'</span>,
<span class="synConstant">'Content-type'</span>: <span class="synConstant">'application/x-www-form-urlencoded'</span>,
<span class="synConstant">'Host'</span>: <span class="synConstant">'www.klnet.pref.kanagawa.jp'</span><span class="synIdentifier">}</span>,
</pre>
<p>
となります。
</p>
<h4>
onloadに続く部分
</h4>
<p>
 以後の部分は、POSTした結果手に入れたものをいじくっています。こいつに検索結果が表示されているので、仮に蔵書があればそこへのリンクを表示させます。もしなければ、見つからなかった旨を表示します。
</p>
<p>
POSTした結果を眺めてみると、蔵書があれば
</p>
<pre class="syntax-highlight">
<span class="synIdentifier">&#60;</span><span class="synStatement">A</span><span class="synIdentifier"> </span><span class="synType">HREF</span><span class="synIdentifier">=</span><span class="synConstant">&#34;OPP1500?ID=1&#38;SELDATA=TOSHO&#38;SEARCHID=0&#38;START=1&#38;ORDER=ASC&#38;ORDER_ITEM=SORT1-F&#38;LISTCNT=20&#38;MAXCNT=100&#38;SEARCHMETHOD=SP_SEARCH&#38;MENUNO=0&#34;</span><span class="synIdentifier">&#62;</span><span class="synUnderlined">1</span><span class="synIdentifier">&#60;/</span><span class="synStatement">A</span><span class="synIdentifier">&#62;</span>
</pre>
<p>
といったように、かならず「OPP1500」ではじまるリンクが与えられているようだと推測できました。なので、
</p>
<pre class="syntax-highlight">
<span class="synStatement">if</span> (response.responseText.match(<span class="synConstant">/OPP1500[^&#34;]*/i</span>)) <span class="synIdentifier">{</span>
<span class="synIdentifier">var</span> result=response.responseText.match(<span class="synConstant">/OPP1500[^&#34;]*/g</span>);
comment = <span class="synConstant">'http://www.klnet.pref.kanagawa.jp/opac/'</span> + result<span class="synIdentifier">[</span><span class="synIdentifier">]</span>;
GM_infoPanel.innerHTML += <span class="synConstant">'&#60;br&#62;&#60;a href=&#34;'</span> + comment + <span class="synConstant">'&#34; target=&#34;blank&#34;&#62;Kanagawa Pref&#60;/a&#62;'</span>;
<span class="synIdentifier">}</span>
<span class="synStatement">else</span><span class="synIdentifier">{</span>
GM_infoPanel.innerHTML += <span class="synConstant">'&#60;br&#62;Kanagawa Pref: Not Found'</span>;
<span class="synIdentifier">}</span>
</pre>
<p>
では、まずOPP1500ではじまるリンクの部分が存在するかどうかをチェックしています。もし存在すれば、リンクの部分を抜き出して、そのリンクに基となる「<a href="http://www.klnet.pref.kanagawa.jp/opac/" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.klnet.pref.kanagawa.jp/opac/', 'http://www.klnet.pref.kanagawa.jp/opac/');" target="_blank">http://www.klnet.pref.kanagawa.jp/opac/</a>」をくっつけて、結果を表示させています。
</p>
<h4>
おわりに
</h4>
<p>
 なんかまずいこと書いているかもしれないので、そのときは教えていただけるとありがたいです(__)
</p>
<div class="hatena-asin-detail">
<a href="http://www.amazon.co.jp/dp/4798015350/?tag=hatena_st1-22&ascsubtag=d-7ibv" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/dp/4798015350/?tag=hatena_st1-22&ascsubtag=d-7ibv', '');"><img src="https://images-na.ssl-images-amazon.com/images/I/51qNllSP91L._SL160_.jpg" class="hatena-asin-detail-image" alt="Greasemonkeyスクリプティング TIPS&SAMPLES" title="Greasemonkeyスクリプティング TIPS&SAMPLES" /></a></p>
<div class="hatena-asin-detail-info">
<p class="hatena-asin-detail-title">
<a href="http://www.amazon.co.jp/dp/4798015350/?tag=hatena_st1-22&ascsubtag=d-7ibv" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.amazon.co.jp/dp/4798015350/?tag=hatena_st1-22&ascsubtag=d-7ibv', 'Greasemonkeyスクリプティング TIPS&#038;SAMPLES');">Greasemonkeyスクリプティング TIPS&SAMPLES</a>
</p>
<ul>
<li>
<span class="hatena-asin-detail-label">作者:</span> <a href="http://d.hatena.ne.jp/keyword/%B9%E2%BB%B3%B6%B3%B2%F0" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/keyword/%B9%E2%BB%B3%B6%B3%B2%F0', '高山恭介');" class="keyword">高山恭介</a>
</li>
<li>
<span class="hatena-asin-detail-label">出版社/メーカー:</span> <a href="http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/keyword/%BD%A8%CF%C2%A5%B7%A5%B9%A5%C6%A5%E0', '秀和システム');" class="keyword">秀和システム</a>
</li>
<li>
<span class="hatena-asin-detail-label">発売日:</span> 2006/12
</li>
<li>
<span class="hatena-asin-detail-label">メディア:</span> 単行本
</li>
<li>
<span class="hatena-asin-detail-label">購入</span>: 1人 <span class="hatena-asin-detail-label">クリック</span>: 92回
</li>
<li>
<a href="http://d.hatena.ne.jp/asin/4798015350" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4798015350', 'この商品を含むブログ (20件) を見る');" target="_blank">この商品を含むブログ (20件) を見る</a>
</li>
</ul>
</div>
<div class="hatena-asin-detail-foot">
</div>
</div>
</div>
<div class="footnote">
<p class="footnote">
<a href="/sirocco634/#fn1" name="f1">*1</a>:今回は関係ないけど、左下には各種オンラインストアへのリンクが表示されるようになっている
</p>
<p class="footnote">
<a href="/sirocco634/#fn2" name="f2">*2</a>ハードカバーと文庫版は異なるisbnが振られていることに注意。また、雑誌や雑貨などにもasinは割り振られているのですが、それらにはisbn10が割り振られていないのでAmazon側で適当な値を割り振っています。一応、そいつも認識するようにしています。こいつはアフィリエート作成のために取っておいたんだけど、はてなに移ってからは使ってないな(..;)
</p>
<p class="footnote">
<a href="/sirocco634/#fn3" name="f3">*3</a>:→<a href="http://www.google.com/search?q=GM_infoPanel%20Greasemonkey&ie=euc-jp" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://www.google.com/search?q=GM_infoPanel%20Greasemonkey&ie=euc-jp', 'google:GM_infoPanel Greasemonkey');" target="_blank">google:GM_infoPanel Greasemonkey</a>しても自分のブログしか出てこないorz。『<a href="http://d.hatena.ne.jp/asin/4798015350" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4798015350', 'Greasemonkeyスクリプティング TIPS&#038;SAMPLES');">Greasemonkeyスクリプティング TIPS&SAMPLES</a>』を参照するのが良いかも。
</p>
</div>