<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>さくらたんどっとびーず &#187; JavaScript</title>
	<atom:link href="http://sakuratan.biz/archives/category/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://sakuratan.biz</link>
	<description>モロモロ工事中です</description>
	<lastBuildDate>Sun, 25 Jun 2023 12:51:51 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>クロスブラウザでdocument.createElement(&#8216;iframe&#8217;)した要素のonloadを呼び出す方法</title>
		<link>http://sakuratan.biz/archives/5044</link>
		<comments>http://sakuratan.biz/archives/5044#comments</comments>
		<pubDate>Tue, 11 Oct 2011 15:38:57 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[DOM]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=5044</guid>
		<description><![CDATA[&#8230;&#8230;.φ（．．）ﾒﾓﾒﾓです。 document.createElement(&#8216;iframe&#8217;) で作った DOM 要素に onload をセットする場合以下のようなコードを使います。 var iframe = document.createElement&#40;'iframe'&#41;; var onload_func = function&#... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/5044">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>&#8230;&#8230;.φ（．．）ﾒﾓﾒﾓです。</p>
<p>document.createElement(&#8216;iframe&#8217;) で作った DOM 要素に onload をセットする場合以下のようなコードを使います。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> iframe <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'iframe'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> onload_func <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// onload で実行する処理</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">all</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>window.<span style="color: #660066;">opera</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// IE の場合 onreadystatechange が必要</span><br />
&nbsp; &nbsp; iframe.<span style="color: #660066;">onreadystatechange</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>iframe.<span style="color: #660066;">readyState</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;complete&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onload_func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// IE 以外なら onload で良い</span><br />
&nbsp; &nbsp; iframe.<span style="color: #000066;">onload</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; onload_func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; <br />
<span style="color: #009900;">&#125;</span><br />
<br />
iframe.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'...'</span><span style="color: #339933;">;</span><br />
parentNode.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>iframe<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>コメントにも書いてますが、IE8 以下の場合 onreadystatechange を使う必要があります。</p>
<h3>参考サイト</h3>
<ul>
<li><a href="http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/">Iframes, onload, and document.domain | NCZOnline</a></li>
</ul>
<h3>あまり参考にならなかったサイト</h3>
<ul>
<li><a href="http://support.microsoft.com/kb/239638/ja">PRB: OnReadyStateChange および IFrame を起動しない OnLoad イベント &#8211; support.microsoft.com</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/5044/feed</wfw:commentRss>
		<slash:comments>533</slash:comments>
		</item>
		<item>
		<title>HTML5が巨人の川相なら、data-属性はHTML5の川相</title>
		<link>http://sakuratan.biz/archives/4479</link>
		<comments>http://sakuratan.biz/archives/4479#comments</comments>
		<pubDate>Thu, 25 Aug 2011 06:31:02 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=4479</guid>
		<description><![CDATA[意味不明なタイトルですんません。増田にインスパイアされました。 さて HTML5 界隈が騒がしい今日このごろですが、data- 属性というものを皆さんご存知でしょうか？ Twitter のツイートボタン作成ページで作った HTML に入ってる data-via とかのことです。最近色んなところでよく目にしますが、これを使うと任意の DOM 要素に任意の値をセットできるみたいです。 で、この dat... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/4479">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>意味不明なタイトルですんません。<a href="http://anond.hatelabo.jp/20110823194555">増田</a>にインスパイアされました。</p>
<p>さて HTML5 界隈が騒がしい今日このごろですが、data- 属性というものを皆さんご存知でしょうか？</p>
<p>Twitter の<a href="https://twitter.com/about/resources/tweetbutton">ツイートボタン作成ページ</a>で作った HTML に入ってる data-via とかのことです。最近色んなところでよく目にしますが、これを使うと任意の DOM 要素に任意の値をセットできるみたいです。</p>
<p>で、この data- 属性なんですが <b>HTML5 の仕様の一部</b>だったみたいです。恥ずかしながらちゃんとした仕様だということを最近知ったのですが、個人的には canvas とか video とかをブッちぎって一番重要な HTML4 からの変更点じゃないかと思います。</p>
<p>てことで本日は、努力家だけど恥ずかしがり屋さんの data- 属性さん(46歳)が実は<a href="http://www.google.com/search?q=%E3%81%84%E3%81%B6%E3%81%97%E9%8A%80&#038;ie=utf-8&#038;oe=utf-8">いぶし銀</a>のスーパースターだということをプロバガンダをしようと思います。</p>
<h3>data- 属性は HTML5 の規格の一部</h3>
<p>まず超基本的なことですが、data- 属性は HTML5 の規格の一部です。</p>
<p>W3C の HTML5 draft の <a href="http://dev.w3.org/html5/spec/elements.html#embedding-custom-non-visible-data-with-the-data-attributes">3.2.3.8 Embedding custom non-visible data with the data-* attributes</a> に定義されています。</p>
<blockquote><p>
Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements.<br />
<cite><a href="http://dev.w3.org/html5/spec/elements.html#embedding-custom-non-visible-data-with-the-data-attributes">3.2.3.8 Embedding custom non-visible data with the data-* attributes</a></cite>
</p></blockquote>
<p>W3C では data- 属性のことを Custom data attributes と呼んでいるようです。日本語では独自データ属性と表記しているサイトが多いと思います（<a href="http://www.html5.jp/tag/attributes/data.html">独自データ属性 &#8211; グローバル属性 &#8211; HTML5 タグリファレンス &#8211; HTML5.JP</a> とか）。</p>
<p style="margin-top:2em">重要なのは↓の部分。（英語の仕様を貼っててもアレなんで HTML5.JP さんから引用）</p>
<blockquote><p>
すべての HTML 要素に対して、独自データ属性をいくつでも、どんな値でも指定することができます。<br />
<a href="http://www.html5.jp/tag/attributes/data.html">独自データ属性 &#8211; グローバル属性 &#8211; HTML5 タグリファレンス &#8211; HTML5.JP</a>
</p></blockquote>
<p>どの要素に何個でも付けれるらしいです(´・ω・`)便利だねー</p>
<p>てことで HTML5 の独自データ属性を使うと、meta タグとか（Twitter がやってた）、type=&#8221;hidden&#8221; の input タグとか（form の下位要素じゃないと HTML 的にまずいような）、display:none にした span とか div とか（なんだかねーって感じ）、id や class 属性とか（属性値に制限あり）に、無理やりセットしてたデータをスマートにコーディングできるようになります。</p>
<h3>使い方</h3>
<p>まず HTML は以下のように書きます。data- に続けてアルファベットと &#8211; で任意のキー名を指定します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;spaceship&quot;</span> data-ship-<span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;92432&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; data-weapons<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;laser 2&quot;</span> data-shields<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;50%&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; data-x<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;30&quot;</span> data-y<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;10&quot;</span> data-z<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;90&quot;</span>&gt;</span>宇宙船ちきう号<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></div>
<p>DOM を使って JavaScript から値を参照する場合は以下のようにコーディングします。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> spaceship <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'spaceship'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>spaceship.<span style="color: #660066;">dataset</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>spaceship.<span style="color: #660066;">dataset</span>.<span style="color: #660066;">weapons</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>spaceship.<span style="color: #660066;">dataset</span>.<span style="color: #660066;">shipId</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>spaceship.<span style="color: #660066;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;data-weapons&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>spaceship.<span style="color: #660066;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;data-ship-id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>上のコードでは dataset プロパティが存在するかチェックして dataset に対応していないブラウザをフォールバックしています。手元の Firefox4 が dataset プロパティに対応していないようでしたので、実際にコーディングする際は getAttribute だけで良いような気もします。</p>
<p>dataset プロパティを使用する場合は、キーに &#8211; が含まれている場合は Camel にします。（data-ship-id → dataset.shipId）</p>
<p>値をセットする場合は dataset プロパティに代入するか setAttribute を使います。jQuery を使った方が便利ですのでこの辺の例は省略、ってことで興味ある方はご自分でお調べください。</p>
<h4>jQuery の場合</h4>
<p>jQuery には <a href="http://api.jquery.com/jQuery.data/">$.data()</a> と <a href="http://api.jquery.com/data">.data()</a> という似たような名前の関数がありまして、HTML5 の独自データ属性と対応するのは <a href="http://api.jquery.com/data">.data()</a> の方なのでご注意ください。$.data() も .data() もプレースホルダを提供する関数なのですが、$.data() の方は完全に jQuery 独自の実装となっています。</p>
<p>で、.data() の方は大方の読者の予想の通り↓のようにコーディングできます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#spaceship'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'weapons'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#spaceship'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ship-id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>値をセットする場合はこんな感じ。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#spaceship'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'weapons'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Gatling gun'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#spaceship'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'weapons'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>ちなみに、.data() で値をセットしても data- 属性には書き込まず $.cache に値がセットされます。data- 属性に書き込みたい場合は <a href="http://api.jquery.com/attr/">.attr()</a> を使ってください。なんかややこい挙動ですが、なんか理由があってこーなってる気がします。（jQuery のサイトでなんで HTML5 の data- に書き込まないの？って感じの<a href="http://api.jquery.com/data">コメント</a>してる人がいますが華麗にスルーされてますし。）</p>
<p>また、.data() の引数を省略するとデータをオブジェクトで返します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#spaceship'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">weapons</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>値にはオブジェクトも指定できます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'bar'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> myType<span style="color: #339933;">:</span> <span style="color: #3366CC;">'test'</span><span style="color: #339933;">,</span> count<span style="color: #339933;">:</span> <span style="color: #CC0000;">40</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'bar'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">myType</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>ぶっちゃけ大して難しいところは無いと思いますので説明はこの辺で。</p>
<p style="margin-top:3em">ということで、いぶし銀 JavaScripter を目指す皆様におかれましては data- 属性で千本バント練習に打ち込むのがよろしいかと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/4479/feed</wfw:commentRss>
		<slash:comments>185</slash:comments>
		</item>
		<item>
		<title>JavaScriptでtextareaのキーボード入力イベントをハンドリングする方法2011年版</title>
		<link>http://sakuratan.biz/archives/3728</link>
		<comments>http://sakuratan.biz/archives/3728#comments</comments>
		<pubDate>Wed, 02 Feb 2011 17:04:23 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[FireFox]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[textarea]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=3728</guid>
		<description><![CDATA[JavaScript プログラマなら、textarea のキーボード入力イベントのハンドリングで一度は苦労したんじゃないかと思います。かく言う私も何度も苦労させられてまっすw で、JavaScript で textarea のキーボード入力イベントを補足する場合、onblur onfocus onchange onkeyup イベントハンドラで行うのが一般的だと思っていたのですが、mozilla（... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/3728">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>JavaScript プログラマなら、textarea のキーボード入力イベントのハンドリングで一度は苦労したんじゃないかと思います。かく言う私も何度も苦労させられてまっすw</p>
<p>で、JavaScript で textarea のキーボード入力イベントを補足する場合、onblur onfocus onchange onkeyup イベントハンドラで行うのが一般的だと思っていたのですが、mozilla（firefox 等）の場合 onkeyup の代わりに onpaste oninput をハンドリングするのが良いようです。</p>
<p>ちーと例示がめんどくさいので jQuery 使ってサンプルコードを書きますとこんな感じになります。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> events <span style="color: #339933;">=</span> <span style="color: #3366CC;">'blur focus change '</span> <span style="color: #339933;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#40;</span>$.<span style="color: #660066;">browser</span>.<span style="color: #660066;">mozilla</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">'paste input'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'keyup'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'textarea'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span>events<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// イベントハンドラ</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>これで textarea にキーボード入力が発生したり、マウスで focus/blur したりといった、ユーザーからの I/O はだいたい補足できると思います。</p>
<p>ちなみに <a href="https://developer.mozilla.org/en/DOM/element#Event_Handlers">onpaste は Mozilla のイベント</a>で、<a href="http://blog.danielfriesen.name/2010/02/16/html5-browser-maze-oninput-support/">oninput は HTML5 のイベント</a>のようです。</p>
<p>んーっと、上のコード Twitter の JavaScript を参考にしたんですが、onpaste が Firefox3 以降なので Firefox2 以下だと textarea が更新されてから change がイベントされないとトリガできないような気もしますが…<br />
まーえーかww</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/3728/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>node.jsとjQueryでスクレイピングするウェブアプリの作り方</title>
		<link>http://sakuratan.biz/archives/3393</link>
		<comments>http://sakuratan.biz/archives/3393#comments</comments>
		<pubDate>Mon, 31 Jan 2011 15:51:06 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[jsdom]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=3393</guid>
		<description><![CDATA[やっぱ jQuery 便利ですよ(*´・ω・)(・ω・｀*)ﾈｰ セレクタ使って jQuery でダカダカやってると、DOM とか正規表現でネチネチやるのがバカらしくなっちゃいます。 と日頃から思ってたりしてまして、サーバサイド JavaScript がメインストリームになって、jQuery でウェブアプリをコーディングできれば超ラクできるかもと期待しています。 で、先日サーバサイドJavaScr... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/3393">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>やっぱ jQuery 便利ですよ(*´・ω・)(・ω・｀*)ﾈｰ</p>
<p>セレクタ使って jQuery でダカダカやってると、DOM とか正規表現でネチネチやるのがバカらしくなっちゃいます。</p>
<p>と日頃から思ってたりしてまして、サーバサイド JavaScript がメインストリームになって、jQuery でウェブアプリをコーディングできれば超ラクできるかもと期待しています。</p>
<p>で、先日<a href="http://sakuratan.biz/archives/2972">サーバサイドJavaScriptとjQueryでスクレイピング</a>という記事をうpったところ、やっぱ Rhino じゃなくて node.js がえーんよ(´･ω･｀)というコメントを頂きましたので、node.js と jQuery でサーバサイド JavaScript スクレイピングしてみることにしました。</p>
<p>今回は node.js ですので、単にスクレイピングする（コマンドラインから実行する）スクリプトだけじゃなくて、スクレイピングする簡単なウェブアプリを作ってみたいと思います。</p>
<p><a href="http://jquery.com/" target="_blank"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/jquery.png" alt="jQuery" width="215" height="53" class="aligncenter size-full wp-image-3609" /></a> <a href="http://nodejs.org/" target="_blank"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/nodejs.png" alt="node.js" width="215" height="53" class="aligncenter size-full wp-image-3610" /></a></p>
<p>結構長文になっちゃったので、先に今日のブログで扱ってるテーマを書いときます。</p>
<ol>
<li>jsdom パッケージを使って node.js で jQuery する方法</li>
<li>jsdom パッケージの HTML コンテンツ中の script タグの扱いに関する問題の回避方法</li>
<li>文字エンコーディングを考慮した HTML コンテンツのダウンロード方法</li>
<li>スクレイピングウェブアプリの作り方</li>
</ol>
<p>あと完成品のソースを入れた ZIP も先に置いときますので、中身から見たいセッカチさんはこちらからどうぞ。</p>
<blockquote><p>
<a href='http://sakuratan.biz/blog/wp-content/uploads/2011/01/nodejs-linkpicker.zip'>nodejs-linkpicker.zip</a>
</p></blockquote>
<h3>要るもの</h3>
<p>まず node.js が必要です。それと node.js のライブラリをインスコするために npm (Node Package Manager）を使います。一緒にインスコしておいてください。</p>
<p>node.js のインスコ方法については <a href="http://nodejs.org/">node.js の公式サイト</a>を、npm のインスコ方法については配布元 github の <a href="https://github.com/isaacs/npm">isaacs /npm</a> をご覧ください。</p>
<p>英語読むのがメンドくせー方は  <a href="http://sakuratan.biz/archives/3101">node.jsとMySQLで割と普通のデータベースウェブアプリを作ってみるチュートリアル</a>に node.js と npm のインスコ方法を書いてますのでそちらとかどうぞ。</p>
<h4>jsdom</h4>
<p>node.js 本体には DOM ライブラリが付いてませんのでそのままでは jQuery を使えませんが、npm パッケージの <a href="http://jsdom.org/">jsdom</a> という DOM ライブラリをインスコすると jQuery も使えるようになります。</p>
<p>jsdom は npm install でインスコできます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>npm <span style="color: #c20cb9; font-weight: bold;">install</span> jsdom</div></div>
<p>とりあえず準備はこれで終わりです。</p>
<h3>jQuery を使ってみる</h3>
<p>早速 node.js で jQuery してみます。</p>
<p>HTML コンテンツに div を追加するスクリプトだとこんな感じになります。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#<span style="color: #339933;">!/</span>usr<span style="color: #339933;">/</span>bin<span style="color: #339933;">/</span>env node<br />
<span style="color: #006600; font-style: italic;">// exam1.js</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sys'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; jsdom <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jsdom'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; domToHtml <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jsdom/browser/domtohtml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> jquery_js <span style="color: #339933;">=</span> <span style="color: #3366CC;">'https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// node、スクリプト名、の次に有効なコマンドライン引数が入る</span><br />
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>process.<span style="color: #660066;">argv</span>.<span style="color: #660066;">length</span> <span style="color: #339933;">&lt;=</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Usage: node exam1.js [FILE]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; process.<span style="color: #660066;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// HTMLコンテンツを読み込む</span><br />
<span style="color: #006600; font-style: italic;">// コマンドライン起動前提なので同期I/Oで</span><br />
<span style="color: #003366; font-weight: bold;">var</span> content <span style="color: #339933;">=</span> fs.<span style="color: #660066;">readFileSync</span><span style="color: #009900;">&#40;</span>process.<span style="color: #660066;">argv</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'utf8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// HTMLコンテンツからwindowオブジェクトを作る</span><br />
<span style="color: #003366; font-weight: bold;">var</span> document <span style="color: #339933;">=</span> jsdom.<span style="color: #660066;">jsdom</span><span style="color: #009900;">&#40;</span>content<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> window <span style="color: #339933;">=</span> document.<span style="color: #660066;">createWindow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// jsdom.jQueryifyがwindowにjQueryを追加してくれる</span><br />
jsdom.<span style="color: #660066;">jQueryify</span><span style="color: #009900;">&#40;</span>window<span style="color: #339933;">,</span> jquery_js<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>window<span style="color: #339933;">,</span> $<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// divを追加する</span><br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;div&gt;More Hello World!!&lt;/div&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// DOMツリーを出力する</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">doctype</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span>String<span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">doctype</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; sys.<span style="color: #000066;">print</span><span style="color: #009900;">&#40;</span>domToHtml.<span style="color: #660066;">domToHtml</span><span style="color: #009900;">&#40;</span>document<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>jQuery 以外の部分が長ったらしいですが、このスクリプトでは大まかに以下の処理を行っています。</p>
<ol>
<li>コマンドライン引数で指定されたファイルを読み込む</li>
<li>jsdom.jsdom() 関数で DOM document オブジェクトを作成</li>
<li>document.createWindow() メソッドを使用し window オブジェクトを作成</li>
<li>window オブジェクトを引数に jsdom.jQueryify 関数を呼び出し jQuery を有効にする</li>
<li>jQuery で処理</li>
</ol>
<p>あと、#!/usr/bin/env node を付けてますので実行パーミッションを与えればそのまま実行可能です。</p>
<p>また、fs.readFileSync() の引数に utf8 を指定してますので、UTF-8 以外のドキュメントだとちゃんと動きません。node.js 本体だけですと ascii／utf-8／base64／binary しか扱えませんので I18N 関係をちゃんと処理しようとすると <a href="https://github.com/bnoordhuis/node-iconv">node-iconv</a> ライブラリなどを使って文字コードを変換する必要があります。後でスクレイピングするスクリプトを書くときにちゃんと対応しますが、とりあえず上のスクリプトは UTF-8 ドキュメントしか処理できません。</p>
<p>他に分からない点があれば <a href="http://nodejs.org/docs/v0.2.6/api.html">node.js のマニュアル</a> をご覧ください。</p>
<p>で、スクリプトを exam1.js に保存します。ついでにテスト用の HTML ファイルを作ります。test1.html として保存してください。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype html&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>テスト<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span>&gt;</span>Hello, World!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>実行すると以下のような出力が得られます。（読みにくいので改行とインデントを追加しています。）</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ node exam1.js test1.html <br />
<span style="color: #000000; font-weight: bold;">&lt;!</span>doctype html<span style="color: #000000; font-weight: bold;">&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;</span>html<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>title<span style="color: #000000; font-weight: bold;">&gt;</span>テスト<span style="color: #000000; font-weight: bold;">&lt;/</span>title<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>body<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>div<span style="color: #000000; font-weight: bold;">&gt;</span>Hello, World<span style="color: #000000; font-weight: bold;">!&lt;/</span>div<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>script <span style="color: #007800;">src</span>=<span style="color: #ff0000;">&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;&lt;/</span>script<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>div<span style="color: #000000; font-weight: bold;">&gt;</span>More Hello World<span style="color: #000000; font-weight: bold;">!!&lt;/</span>div<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span>body<span style="color: #000000; font-weight: bold;">&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;/</span>html<span style="color: #000000; font-weight: bold;">&gt;</span></div></div>
<h3>jsdom.jsdom() と jsdom.jQueryify()</h3>
<p>上の例を見ればだいたいお分かり頂けると思いますが node.js で jQuery を使う場合、</p>
<ol>
<li>jsdom.jsdom() で document オブジェクトを作成</li>
<li>document.createWindow() メソッドで window オブジェクトを作成</li>
<li>window オブジェクトに対して jsdom.jQueryify() を呼び出して jQuery オブジェクトを作成</li>
</ol>
<p>という手順が必要になります。</p>
<p>jsdom.jsdom() と jsdom.jQueryify() のパラメータは結構ややこいと思いますので先に説明します。</p>
<h4>jsdom.jsdom() 関数の使い方</h4>
<p>HTML コンテンツを DOM document オブジェクトに変換する関数です。jsdom.jsdom() のプロトタイプは以下のようになります。level 引数と options 引数はオプションです。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">jsdom.<span style="color: #660066;">jsdom</span><span style="color: #009900;">&#40;</span>body<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>level<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>options<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>body 引数には DOM ツリーを作成する元となる HTML コンテンツ（文字列）を渡します。URL やパスを指定してファイルから直接 document オブジェクトを作成する方法はありません。</p>
<p>level 引数には使用したい DOM レベルに合わせた DOM HTML オブジェクトを渡す必要があります。省略するか、false や null などの偽評価される値を渡すと、DOM Level2 HTML 相当のオブジェクトが使用されます。（実際には DOM Level3 HTML 相当の DOM オブジェクトがデフォルト値なのですが、DOM Level3 は実装中のようで機能的には DOM Level2 になっています。）</p>
<p>level 引数に DOM Level1 を渡す場合は以下のようにコーディングします。ただあまり使い道は無いと思いますので、普段は null を渡しとけば良いと思います。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> jsdom <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jsdom'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; dom_level1 <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jsdom/level1/core'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">dom</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> document <span style="color: #339933;">=</span> jsdom.<span style="color: #660066;">jsdom</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #339933;">,</span> dom_level1.<span style="color: #660066;">html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>options 引数は DOM document を作成する際に使用するオプションを指定するオブジェクトです。</p>
<p>オプションとして有効な値とデフォルト値は以下のとおりです。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; url<span style="color: #339933;">:</span> undefined<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; features<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; FetchExternalResources &nbsp;<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'script'</span><span style="color: #006600; font-style: italic;">/*, 'img', 'css', 'frame', 'link'*/</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ProcessExternalResources<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'script'</span><span style="color: #006600; font-style: italic;">/*, 'frame', 'iframe'*/</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; QuerySelector &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>各オプションの意味は以下のようになっています。</p>
<ul>
<li>url（文字列）<br />
HTML コンテンツの baseURI。<br />
コンテンツに含まれる相対パスの baseURI として使用されます。<br />
省略時は baseURI が存在しないため相対パスはそのまま処理されます。その場合、コンテンツ中の相対パスで指定された外部リソースの取得は失敗します。</li>
<li>features.FetchExternalResources（配列）<br />
外部リソースを取得するタグを列挙します。デフォルトでは script タグで指定されたファイルを取得します。<br />
空文字列または null など偽評価値を渡すと外部リソースをダウンロードしなくなります。</li>
<li>features.ProcessExternalResources（配列）<br />
外部リソースから実行するタグを列挙します。デフォルトでは script タグの JavaScript を実行します。<br />
空文字列または null など偽評価値を渡すと外部リソースを実行しなくなります。</li>
<li>QuerySelector（Boolean）<br />
true の場合、<a href="http://sizzlejs.com/">Sizzle CSS Selector Engine</a> を有効にします。デフォルトは false です。<br />
（jQuery を使う場合は、jQuery 本体に CSS Selector が含まれていますので QuerySelector を有効にする必要はありません。）</li>
</ul>
<p>ちなみに、document オブジェクト自体は不要で window オブジェクトだけが欲しい場合は以下のようにコーディングすることもできます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> window <span style="color: #339933;">=</span> jsdom.<span style="color: #660066;">jsdom</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">createWindow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h4>jsdom.jQueryify() 関数の使い方</h4>
<p>jsdom.jQueryify() 関数は document.createWindow() メソッドにより作成した window オブジェクトに対し jQueryify（jQuery 化）を行います。</p>
<p>jsdom.jQueryify() のプロトタイプは以下のとおりです。path 引数と callback 引数はオプションです。第三引数を省略した場合、第二引数が文字列なら path 引数として扱われ、第二引数が関数なら callback 引数として扱われます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">jsdom.<span style="color: #660066;">jQueryify</span><span style="color: #009900;">&#40;</span>window<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#91;</span>path<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> callback<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span></div></div>
<p>window 引数には jsdom.jsdom().createWindow() を使って作成した window オブジェクトを渡します。</p>
<p>path 引数には jQuery ソースコードの置かれたパスまたは URL を渡します。この引数を省略すると http://code.jquery.com/jquery-latest.js から jQuery のソースコードを読み込もうとします。（不要かもしれませんが）サーバ負荷を考慮して上の例では <a href="http://code.google.com/intl/ja/apis/libraries/">Google Libraries API</a> の <a href="http://code.google.com/intl/ja/apis/libraries/devguide.html#jquery">jQuery</a> を指定するようにしています。</p>
<p>path 引数にローカルの jQuery ファイルのパスを指定することもできますが、jsdom.jQueryify() は HTML コンテンツに path 引数の script タグを埋め込むことで jQuery の初期化を行っているため、document オブジェクトのオプションで指定した baseURI の値によっては、ローカルの jQuery ファイルを指定すると jQuery の読み込みに失敗することがあります。（baseURI/path を読み込もうとして失敗する。）</p>
<p>なので、この引数には通常 HTTP 経由でアクセスできる URL を指定してください。（file: プロトコルを指定しても意味がないようですので http: プロトコルでアクセス可能な URL が必要です。）</p>
<p>なお、この path 引数の処理の仕方は、jsdom.jsdom() で document を作成する過程と合わせて問題になることがあります。（この問題については以下の <a href="#problem">HTML コンテンツ中の script タグの扱いについて</a> で説明します。）</p>
<p>callback 引数には jQuery の初期化に成功した際に呼ばれるコールバック関数を渡します。コールバック関数のプロトタイプは以下のとおりです。window には jsdom.jQueryify() の第一引数に指定された window オブジェクトが、$ には jQuery オブジェクトが渡されます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">callback<span style="color: #009900;">&#40;</span>window<span style="color: #339933;">,</span> $<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h3 id="problem">HTML コンテンツ中の script タグの扱いについて</h3>
<p>jsdom.jsdom() 関数は、HTML コンテンツを DOM ツリーに変換する過程で HTML コンテンツに含まれるすべての script タグを実行します。</p>
<p>例えば先ほどの test1.html を以下のように書き換え script タグを追加し、</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;!doctype html&gt;<br />
&lt;html&gt;<br />
&nbsp; &lt;head&gt;<br />
&nbsp; &nbsp; &lt;title&gt;テスト&lt;/title&gt;<br />
&nbsp; &nbsp; <span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;security vulnerability&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span><br />
&nbsp; &lt;/head&gt;<br />
&nbsp; &lt;body&gt;<br />
&nbsp; &nbsp; &lt;div&gt;Hello, World!&lt;/div&gt;<br />
&nbsp; &lt;/body&gt;<br />
&lt;/html&gt;</div></div>
<p>再度 exam1.js を実行すると以下のような出力が得られます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ node exam1.js test1.html<br />
security vulnerability<br />
security vulnerability<br />
<span style="color: #000000; font-weight: bold;">&lt;!</span>doctype html<span style="color: #000000; font-weight: bold;">&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;</span>html<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>title<span style="color: #000000; font-weight: bold;">&gt;</span>テスト<span style="color: #000000; font-weight: bold;">&lt;/</span>title<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>script <span style="color: #007800;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; console.log<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">&quot;security vulnerability&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span>script<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>body<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>div<span style="color: #000000; font-weight: bold;">&gt;</span>Hello, World<span style="color: #000000; font-weight: bold;">!&lt;/</span>div<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>script <span style="color: #007800;">src</span>=<span style="color: #ff0000;">&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;&lt;/</span>script<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>div<span style="color: #000000; font-weight: bold;">&gt;</span>More Hello World<span style="color: #000000; font-weight: bold;">!!&lt;/</span>div<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span>body<span style="color: #000000; font-weight: bold;">&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;/</span>html<span style="color: #000000; font-weight: bold;">&gt;</span></div></div>
<p>jsdom.jsdom() が HTML コンテンツ中の JavaScript を実行しちゃってます。（security vulnerability メッセージがなんで二回出力されるのかは重要ではないので調べていません。）</p>
<p>jsdom のソースを見ますと、script タグに含まれる JavaScript は node.js の Script.runInContext() メソッドにより実行されています。</p>
<p>単純に eval せず runInContext() でラップしているため script タグから require 等は使用できません。そのため script タグ中の JavaScript から実行できることは限られていますが、ログを埋め尽くしたり無限ループを作ったりぐらいはできます。また document.write の動作がブラウザ上での動作とちょっと違ったりします（document.write の出力先が常に document 先頭になってるようです）ので、そのままサーバサイドスクリプトに組み込むのはちょっと厳しい感じです。</p>
<p>また script タグに src 属性が指定されている場合、src で指定されたファイルをダウンロードして実行します。そのためネットワークアクセスが必要なコンテンツの場合は処理に時間がかかるという問題もあります。</p>
<p>いずれにしてもこのままではスクレイピング用途には使いにくいので、HTML 中の script タグの処理を無効にする必要があります。ただ jsdom.jQueryify() の jQuery の実行方法に問題があり単純に無効にすることはできません。</p>
<p>以下に jQuery の実行方法のどの辺が問題か説明します。</p>
<h4>1. jsdom.jsdom() で script タグの無効にする</h4>
<p>まず HTML 中の script タグの処理を無効にすること自体は、jsdom.jsdom() のオプション引数で features.FetchExternalResources と features.ProcessExternalResources を false にすることで実現できます。</p>
<p>具体的には以下のように jsdom.jsdom() を呼び出します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> document <span style="color: #339933;">=</span> jsdom.<span style="color: #660066;">jsdom</span><span style="color: #009900;">&#40;</span>content<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; features<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; FetchExternalResources<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ProcessExternalResources<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>ここまでは特に問題ありません。</p>
<h4>2. jsdom.jQueryify() の jQuery 埋め込み方法</h4>
<p>jsdom.jQueryify() では jQuery を実行するのに、HTML コンテンツの末尾に jsdom.jQueryify() の第二引数を src 属性に指定した script 要素を appendChild() メソッドを使って HTML body に追加する方法で行っています。</p>
<p>HTML コンテンツ中の JavaScript は jsdom ライブラリにより実行されますので、appendChild() されるタイミングで埋め込まれた jQuery スクリプトが実行されるという仕組みです。</p>
<p>先ほどのスクリプトの実行結果を見ると src=&#8221;https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js&#8221; を持つ script タグが埋め込まれていますが、これは上記の仕組みにより jsdom.jQueryify()  が追加したものです。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span>&gt;</span>Hello, World!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span>&gt;</span>More Hello World!!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></div>
<p>この動作自体も特に問題という訳ではありません。</p>
<h4>3. 1 と 2 を合わせると動かなくなる</h4>
<p>script タグの処理を無効にするには、jsdom.jsdom() を呼び出す際に options.features.FetchExternalResources と options.features.ProcessExternalResources を false にすれば良いです。これらのオプションを指定すると document に含まれる script タグがまったく実行されなくなります。</p>
<p>jsdom.jQueryify() は jQuery を埋め込むのに、DOM ツリーに script タグを埋め込みますが、jsdom.jsdom() で script の実行を無効にするとこの処理も無効になります。</p>
<p>これらを合わせると、jsdom.jsdom() のオプションを指定して script タグの処理を無効にすると、jsdom.jQueryify() も使用できなくなります。問題です。</p>
<h3>jsdom.jQueryify() を使用せずに jQuery を実行する</h3>
<p>とりあえずscript タグの処理を無効にして jsdom.jsdom() と jsdom.jQueryify() を使用できないということになりましたので、jQueryify と似たような処理を自前で実装することにしました。</p>
<p>以下の embedJQuery() 関数がその辺のややこいところを全部処理します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// embedJQuery.js</span><br />
<span style="color: #006600; font-style: italic;">// jsdomとjQueryのラッパー</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; Script <span style="color: #339933;">=</span> process.<span style="color: #660066;">binding</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'evals'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Script</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; jsdom <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jsdom'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; httpsubr <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./httpsubr'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// jQuery を読み込む</span><br />
<span style="color: #003366; font-weight: bold;">var</span> jQueryPath <span style="color: #339933;">=</span> __dirname <span style="color: #339933;">+</span> <span style="color: #3366CC;">'/jquery.min.js'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> jQueryScript <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Script<span style="color: #009900;">&#40;</span>fs.<span style="color: #660066;">readFileSync</span><span style="color: #009900;">&#40;</span>jQueryPath<span style="color: #339933;">,</span> <span style="color: #3366CC;">'utf-8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jQueryPath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// HTMLコンテンツにjQueryを埋め込み、</span><br />
<span style="color: #006600; font-style: italic;">// windowオブジェクトとjQueryオブジェクトを返す</span><br />
exports.<span style="color: #660066;">embedJQuery</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>body<span style="color: #339933;">,</span> options<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// HTMLファイル中のscriptタグの処理を無効にしてwindowを作成</span><br />
&nbsp; &nbsp; options <span style="color: #339933;">=</span> options <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; options.<span style="color: #660066;">features</span> <span style="color: #339933;">=</span> options.<span style="color: #660066;">features</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; options.<span style="color: #660066;">features</span>.<span style="color: #660066;">FetchExternalResources</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; options.<span style="color: #660066;">features</span>.<span style="color: #660066;">ProcessExternalResources</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> window <span style="color: #339933;">=</span> jsdom.<span style="color: #660066;">jsdom</span><span style="color: #009900;">&#40;</span>body<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> options<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">createWindow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// jQueryを実行</span><br />
&nbsp; &nbsp; jQueryScript.<span style="color: #660066;">runInNewContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; window<span style="color: #339933;">:</span> window<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; navigator<span style="color: #339933;">:</span> window.<span style="color: #660066;">navigator</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; location<span style="color: #339933;">:</span> window.<span style="color: #660066;">location</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; setTimeout<span style="color: #339933;">:</span> setTimeout<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// callbackを呼び出す</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> window<span style="color: #339933;">,</span> window.<span style="color: #660066;">jQuery</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// URLからリソースを読み込みjQueryを追加する</span><br />
exports.<span style="color: #660066;">jQueryRequest</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>targetUrl<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; httpsubr.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> uri<span style="color: #339933;">:</span> targetUrl <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> response<span style="color: #339933;">,</span> raw<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>response.<span style="color: #660066;">statusCode</span> <span style="color: #339933;">!=</span> <span style="color: #CC0000;">200</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Error<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;HTTP Error&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> body <span style="color: #339933;">=</span> httpsubr.<span style="color: #660066;">convertCharset</span><span style="color: #009900;">&#40;</span>response<span style="color: #339933;">,</span> raw<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// コンテンツのbaseURIをtargetUrlにするためurlオプションを指定</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; exports.<span style="color: #660066;">embedJQuery</span><span style="color: #009900;">&#40;</span>body<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> url<span style="color: #339933;">:</span> targetUrl <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>embedJQuery.js ではローカルの jQuery を読み込むようにしています。jQuery 1.4.2 〜 1.4.4 とともに動くようにコーディングしていますので、予め <a href="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js">https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js</a> などからファイルをダウンロードして embedJQuery.js と同じディレクトリに置いてください。ファイル名が jquery.min.js 以外のときは、jQueryPath 変数の値を書き換えてください。</p>
<p>先ほどの exam1.js を embedJQuery() 関数を使用するように書き換えると以下のようになります。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#<span style="color: #339933;">!/</span>usr<span style="color: #339933;">/</span>bin<span style="color: #339933;">/</span>env node<br />
<span style="color: #006600; font-style: italic;">// exam2.js</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sys'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; domToHtml <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jsdom/browser/domtohtml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; embedJQuery <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./embedJQuery'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">embedJQuery</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> jquery_js <span style="color: #339933;">=</span> <span style="color: #3366CC;">'https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>process.<span style="color: #660066;">argv</span>.<span style="color: #660066;">length</span> <span style="color: #339933;">&lt;=</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Usage: node exam2.js [FILE]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; process.<span style="color: #660066;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> content <span style="color: #339933;">=</span> fs.<span style="color: #660066;">readFileSync</span><span style="color: #009900;">&#40;</span>process.<span style="color: #660066;">argv</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'utf8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// jsdom.jQueryifyがwindowにjQueryを追加してくれる</span><br />
embedJQuery<span style="color: #009900;">&#40;</span>content<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> window<span style="color: #339933;">,</span> $<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'body'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;div&gt;More Hello World!!&lt;/div&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> document <span style="color: #339933;">=</span> window.<span style="color: #660066;">document</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">doctype</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span>String<span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">doctype</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; sys.<span style="color: #000066;">print</span><span style="color: #009900;">&#40;</span>domToHtml.<span style="color: #660066;">domToHtml</span><span style="color: #009900;">&#40;</span>document<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>テスト用に無限ループを組み込んだ HTML を用意し、</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype html&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>テスト<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; console.log(&quot;security vulnerability&quot;);<br />
&nbsp; &nbsp; &nbsp; for (;;) ;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span>&gt;</span>Hello, World!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>exam2.js を実行すると以下のようになります。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ node exam2.js test2.html <br />
<span style="color: #000000; font-weight: bold;">&lt;!</span>doctype html<span style="color: #000000; font-weight: bold;">&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;</span>html<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>title<span style="color: #000000; font-weight: bold;">&gt;</span>テスト<span style="color: #000000; font-weight: bold;">&lt;/</span>title<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>script <span style="color: #007800;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; console.log<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">&quot;security vulnerability&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">;;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> ;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span>script<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;/</span><span style="color: #c20cb9; font-weight: bold;">head</span><span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>body<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>div<span style="color: #000000; font-weight: bold;">&gt;</span>Hello, World<span style="color: #000000; font-weight: bold;">!&lt;/</span>div<span style="color: #000000; font-weight: bold;">&gt;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">&lt;</span>div<span style="color: #000000; font-weight: bold;">&gt;</span>More Hello World<span style="color: #000000; font-weight: bold;">!!&lt;/</span>div<span style="color: #000000; font-weight: bold;">&gt;&lt;/</span>body<span style="color: #000000; font-weight: bold;">&gt;</span><br />
<span style="color: #000000; font-weight: bold;">&lt;/</span>html<span style="color: #000000; font-weight: bold;">&gt;</span></div></div>
<p>同じ HTML コンテンツを exam1.js で処理すると、for (;;) ; の部分で無限ループになり帰ってきませんが、exam2.js では embedJQuery が script タグを処理しないようにしてるので処理は終了します。また jQuery を使って埋め込んだ div タグもちゃんと表示されています。</p>
<h3>複数の文字エンコーディングに対応させる</h3>
<p>日本語の HTML コンテンツの場合 Shift_JIS / EUC-JP / UTF-8 等の文字エンコーディングを使用しますが、node.js 本体には UTF-8 以外の文字エンコーディングを処理する機能は付いてません。</p>
<p>日本語のコンテンツを処理するためには、<a href="https://github.com/bnoordhuis/node-iconv">node-iconv</a> パッケージ等を使用してダウンロードしたコンテンツを node.js で処理可能な文字コードに変換する必要があります。</p>
<p>node-iconv パッケージは npm からインスコできませんので、github からソースをダウンロードしてビルドする必要があります。</p>
<p>node-iconv の github には、node.js バージョン 0.3 系列向けのブランチとバージョン 0.2 系列向けのブランチが用意されています。</p>
<p>ブランチを指定せず git clone すると 0.3 系列向けのソースがダウンロードされます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git clone</span> git:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>bnoordhuis<span style="color: #000000; font-weight: bold;">/</span>node-iconv.git</div></div>
<p>0.2 系列向けのソースが必要な場合は、-b オプションを付けて v0.2.x ブランチをダウンロードしてください。（v0.2.6 等、node.js の個別のバージョン向けのブランチが用意されているわけではありません。v0.2.x ブランチをダウンロードしてください。）</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">git clone</span> <span style="color: #660033;">-b</span> v0.2.x git:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>bnoordhuis<span style="color: #000000; font-weight: bold;">/</span>node-iconv.git</div></div>
<p>ビルドは make のみです。NODE_PATH 引数には node.js をインストールしたプレフィクスを指定してください。デフォルトは /usr/local です。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">make</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span> <span style="color: #007800;">NODE_PATH</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">local</span></div></div>
<p>node-iconv がインスコできたら、文字コードを考慮した HTTP クライアントモジュールを作ります。</p>
<p>node.js でオクテットを扱う場合は、通常 Buffer オブジェクトを使用します。Buffer オブジェクトを String（文字列）オブジェクトに変換するには、buffer.toString(encoding) メソッドを使用します。</p>
<p>今から作るモジュールは <a href="https://github.com/mikeal/node-utils">request</a> パッケージを参考にしていまして、request パッケージの関数が HTTP レスポンスを Buffer オブジェクトじゃなくて文字列で返してくるため、node-iconv にそのままレスポンスを渡すと文字化けするようなのでその辺を直した感じのものになっています。</p>
<p>ちなみに node-iconv は、libiconv が文字コード変換に失敗し EILSEQ エラーが発生した場合、常に例外を発生します。一般的な LL 言語の文字コード変換ライブラリでは、文字コード変換に失敗したら適当な代替え文字で差し替える処理が実装されていると思いますが、node-iconv ではそういった処理はできませんので注意してください。ただ今回は node.js と jQuery がメインですので、この辺にはこれ以上触れずに進めます。</p>
<p>ということで書いたコードは↓です。HTTP レスポンスと Buffer オブジェクトから文字コードを検出して文字列に変換する関数と、HTTP リクエストのラッパー関数を実装しています。</p>
<p>HTTP リクエスト関数では、生の Buffer オブジェクトではなく文字コード変換した文字列をコールバック関数に返すようにもできますが、エラー処理が分かりにくくなりそうなので raw buffer を返すことにしてます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// httpsubr.js</span><br />
<span style="color: #006600; font-style: italic;">// HTTP関連のサブルーチン</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> http <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; iconv <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'iconv'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; url <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'url'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// Bufferを連結する</span><br />
<span style="color: #003366; font-weight: bold;">function</span> concatBuffer<span style="color: #009900;">&#40;</span>src1 <span style="color: #006600; font-style: italic;">/* , src2, ... */</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> start<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> len <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> arguments.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; len <span style="color: #339933;">+=</span> arguments<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">length</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; buf <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Buffer<span style="color: #009900;">&#40;</span>len<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; start <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> arguments.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> chunk <span style="color: #339933;">=</span> arguments<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; chunk.<span style="color: #660066;">copy</span><span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> start<span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; start <span style="color: #339933;">+=</span> chunk.<span style="color: #660066;">length</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> buf<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// HTTPレスポンスとBufferからエンコーディングを検出し</span><br />
<span style="color: #006600; font-style: italic;">// レスポンスボディを文字列で返す</span><br />
exports.<span style="color: #660066;">convertCharset</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #339933;">,</span> buf<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> charset <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> content_type <span style="color: #339933;">=</span> response.<span style="color: #660066;">headers</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'content-type'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>content_type<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; re <span style="color: #339933;">=</span> content_type.<span style="color: #660066;">match</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/\bcharset=([\w\-]+)\b/i</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>re<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; charset <span style="color: #339933;">=</span> re<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>charset<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> bin <span style="color: #339933;">=</span> buf.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'binary'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; re <span style="color: #339933;">=</span> bin.<span style="color: #660066;">match</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/&lt;meta\b[^&gt;]*charset=([\w\-]+)/i</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>re<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; charset <span style="color: #339933;">=</span> re<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; charset <span style="color: #339933;">=</span> <span style="color: #3366CC;">'utf-8'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>charset<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'ascii'</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'utf-8'</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> buf.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span>charset<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ic <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> <span style="color: #009900;">&#40;</span>iconv.<span style="color: #660066;">Iconv</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>charset<span style="color: #339933;">,</span> <span style="color: #3366CC;">'utf-8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> buf2 <span style="color: #339933;">=</span> ic.<span style="color: #660066;">convert</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> buf2.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'utf8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// 文字列ではなくBufferを返す版の</span><br />
<span style="color: #006600; font-style: italic;">// requestパッケージ (https://github.com/mikeal/node-utils) のrequest関数</span><br />
<span style="color: #006600; font-style: italic;">// とほぼ同等な関数</span><br />
<span style="color: #006600; font-style: italic;">// request関数にある一部機能は実装していない</span><br />
exports.<span style="color: #660066;">httpRequest</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>options<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; options <span style="color: #339933;">=</span> options <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'string'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; options.<span style="color: #660066;">uri</span> <span style="color: #339933;">=</span> url.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; options.<span style="color: #660066;">method</span> <span style="color: #339933;">=</span> options.<span style="color: #660066;">method</span> <span style="color: #339933;">||</span> <span style="color: #3366CC;">'GET'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; options.<span style="color: #660066;">headers</span> <span style="color: #339933;">=</span> options.<span style="color: #660066;">headers</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; options._nRedirect <span style="color: #339933;">=</span> options._nRedirect <span style="color: #339933;">||</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">maxRedirects</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; options.<span style="color: #660066;">maxRedirects</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>options.<span style="color: #660066;">headers</span>.<span style="color: #660066;">host</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; options.<span style="color: #660066;">headers</span>.<span style="color: #660066;">host</span> <span style="color: #339933;">=</span> options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">hostname</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">port</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; options.<span style="color: #660066;">headers</span>.<span style="color: #660066;">host</span> <span style="color: #339933;">+=</span> <span style="color: #3366CC;">':'</span> <span style="color: #339933;">+</span> options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">port</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> port <span style="color: #339933;">=</span> <span style="color: #CC0000;">80</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> https <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">protocol</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'https:'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; port <span style="color: #339933;">=</span> <span style="color: #CC0000;">443</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; https <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">port</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; port <span style="color: #339933;">=</span> port<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> path <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">pathname</span> <span style="color: #339933;">?</span> options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">pathname</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">search</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; path <span style="color: #339933;">+=</span> options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">search</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">hash</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; path <span style="color: #339933;">+=</span> options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">hash</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> client <span style="color: #339933;">=</span> http.<span style="color: #660066;">createClient</span><span style="color: #009900;">&#40;</span>port<span style="color: #339933;">,</span> options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">hostname</span><span style="color: #339933;">,</span> https<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">addListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'error'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> request <span style="color: #339933;">=</span> client.<span style="color: #660066;">request</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">method</span><span style="color: #339933;">,</span> path<span style="color: #339933;">,</span> options.<span style="color: #660066;">headers</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; request.<span style="color: #660066;">addListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'response'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>response.<span style="color: #660066;">headers</span>.<span style="color: #660066;">location</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options._nRedirect<span style="color: #339933;">++</span> <span style="color: #339933;">&gt;=</span> options.<span style="color: #660066;">maxRedirect</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">emit</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'error'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Error<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Too many redirects'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> loc <span style="color: #339933;">=</span> response.<span style="color: #660066;">headers</span>.<span style="color: #660066;">location</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>loc.<span style="color: #660066;">match</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^https?:/i</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loc <span style="color: #339933;">=</span> url.<span style="color: #660066;">resolve</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">uri</span>.<span style="color: #660066;">href</span><span style="color: #339933;">,</span> response.<span style="color: #660066;">headers</span>.<span style="color: #660066;">location</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; options.<span style="color: #660066;">uri</span> <span style="color: #339933;">=</span> loc<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exports.<span style="color: #660066;">httpRequest</span><span style="color: #009900;">&#40;</span>options<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> chunks <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'data'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>chunk<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chunks.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>chunk<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'end'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> buf <span style="color: #339933;">=</span> concatBuffer.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> chunks<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">delete</span><span style="color: #009900;">&#40;</span>chunks<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> response<span style="color: #339933;">,</span> buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">requestBody</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">requestBody</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'string'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.<span style="color: #000066; font-weight: bold;">write</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">requestBody</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; request.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">pump</span><span style="color: #009900;">&#40;</span>options.<span style="color: #660066;">requestBody</span><span style="color: #339933;">,</span> request<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; request.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
exports.<span style="color: #660066;">get</span> <span style="color: #339933;">=</span> exports.<span style="color: #660066;">httpRequest</span><span style="color: #339933;">;</span><br />
<br />
exports.<span style="color: #660066;">post</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>options<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>options.<span style="color: #660066;">requestBody</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; options.<span style="color: #660066;">requestBody</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; exports.<span style="color: #660066;">request</span><span style="color: #009900;">&#40;</span>options<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>マジでスクレイピングする</h3>
<p>jQuery を使ってスクレイピングする準備が整いましたので、ネットワークから HTML を読み込んでスクレイピングするスクリプトを作ります。</p>
<h4>スクレイピングするモジュール</h4>
<p>まずネットワークから HTML を読み込みスクレイピングする部分のモジュールを作ります。a タグを読み込んでサーバ別にリンクを取得する関数と、リンクの配列をホスト別に分類してソートする関数を実装しています。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// linkPicker.js</span><br />
<span style="color: #006600; font-style: italic;">// HTMLコンテンツからリンク（aタグ）を取り出す</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'url'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; embedJQuery <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./embedJQuery'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// jQueryでaタグを取り出しcallbackを起動</span><br />
exports.<span style="color: #660066;">pickupLinks</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>targetUrl<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; embedJQuery.<span style="color: #660066;">jQueryRequest</span><span style="color: #009900;">&#40;</span>targetUrl<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> window<span style="color: #339933;">,</span> $<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> links <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; links.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>url.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span>String<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">href</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; links.<span style="color: #660066;">sort</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a.<span style="color: #660066;">href</span> <span style="color: #339933;">&lt;</span> b.<span style="color: #660066;">href</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a.<span style="color: #660066;">href</span> <span style="color: #339933;">&gt;</span> b.<span style="color: #660066;">href</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> links<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// リンクをホストごとに分類してソート</span><br />
exports.<span style="color: #660066;">sortLinksByHost</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>links<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">,</span> j<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> host <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> hosts <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> hostLinks <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> links.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> link <span style="color: #339933;">=</span> links<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> fqHost <span style="color: #339933;">=</span> link.<span style="color: #660066;">protocol</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>link.<span style="color: #660066;">slashes</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fqHost <span style="color: #339933;">+=</span> <span style="color: #3366CC;">'//'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fqHost <span style="color: #339933;">+=</span> link.<span style="color: #660066;">host</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>host <span style="color: #339933;">!=</span> fqHost<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; host <span style="color: #339933;">=</span> fqHost<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hosts.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>fqHost<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hostLinks<span style="color: #009900;">&#91;</span>fqHost<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; hostLinks<span style="color: #009900;">&#91;</span>fqHost<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>link<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span> hosts<span style="color: #339933;">:</span>hosts<span style="color: #339933;">,</span> hostLinks<span style="color: #339933;">:</span>hostLinks <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h4>コマンドラインからスクレイピング</h4>
<p>コマンドラインから起動され、上の linkPicker.js を使ってスクレイピングするスクリプトはこんな感じになります。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#<span style="color: #339933;">!/</span>usr<span style="color: #339933;">/</span>bin<span style="color: #339933;">/</span>env node<br />
<span style="color: #006600; font-style: italic;">// client.js</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sys'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; linkPicker <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./linkPicker'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
process.<span style="color: #660066;">argv</span>.<span style="color: #660066;">forEach</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>val<span style="color: #339933;">,</span> index<span style="color: #339933;">,</span> array<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>index <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; linkPicker.<span style="color: #660066;">pickupLinks</span><span style="color: #009900;">&#40;</span>val<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> links<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span>val <span style="color: #339933;">+</span> <span style="color: #3366CC;">' contains '</span> <span style="color: #339933;">+</span> links.<span style="color: #660066;">length</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">' links'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> sorted <span style="color: #339933;">=</span> linkPicker.<span style="color: #660066;">sortLinksByHost</span><span style="color: #009900;">&#40;</span>links<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> sorted.<span style="color: #660066;">hosts</span>.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> host <span style="color: #339933;">=</span> sorted.<span style="color: #660066;">hosts</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'¥t'</span> <span style="color: #339933;">+</span> host <span style="color: #339933;">+</span> <span style="color: #3366CC;">', '</span> <span style="color: #339933;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sorted.<span style="color: #660066;">hostLinks</span><span style="color: #009900;">&#91;</span>host<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">length</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">' links'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> j <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;</span> sorted.<span style="color: #660066;">hostLinks</span><span style="color: #009900;">&#91;</span>host<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>j<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'¥t¥t'</span> <span style="color: #339933;">+</span> sorted.<span style="color: #660066;">hostLinks</span><span style="color: #009900;">&#91;</span>host<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">href</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>スクリプトに実行パーミッションをセットし、必要なファイル（embedJQuery.js、jquery.min.js、linkPicker.js）をこのスクリプトと同じディレクトリに置いてから、スクレイピングしたい URL を引数に実行すると、こんな感じに a タグのリンクを表示します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ .<span style="color: #000000; font-weight: bold;">/</span>client.js &nbsp;http:<span style="color: #000000; font-weight: bold;">//</span>www.google.co.jp<span style="color: #000000; font-weight: bold;">/</span><br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.google.co.jp<span style="color: #000000; font-weight: bold;">/</span> contains <span style="color: #000000;">28</span> links<br />
&nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>blogsearch.google.co.jp, <span style="color: #000000;">1</span> links<br />
&nbsp; &nbsp; &nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>blogsearch.google.co.jp<span style="color: #000000; font-weight: bold;">/</span>?<span style="color: #007800;">hl</span>=ja<span style="color: #000000; font-weight: bold;">&amp;</span><span style="color: #007800;">tab</span>=wb<br />
&nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>books.google.co.jp, <span style="color: #000000;">1</span> links<br />
&nbsp; &nbsp; &nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>books.google.co.jp<span style="color: #000000; font-weight: bold;">/</span>bkshp?<span style="color: #007800;">hl</span>=ja<span style="color: #000000; font-weight: bold;">&amp;</span><span style="color: #007800;">tab</span>=wp<br />
&nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>docs.google.com, <span style="color: #000000;">1</span> links<br />
&nbsp; &nbsp; &nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>docs.google.com<span style="color: #000000; font-weight: bold;">/</span>?<span style="color: #007800;">hl</span>=ja<span style="color: #000000; font-weight: bold;">&amp;</span><span style="color: #007800;">tab</span>=wo<br />
&nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>groups.google.co.jp, <span style="color: #000000;">1</span> links<br />
&nbsp; &nbsp; &nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>groups.google.co.jp<span style="color: #000000; font-weight: bold;">/</span>grphp?<span style="color: #007800;">hl</span>=ja<span style="color: #000000; font-weight: bold;">&amp;</span><span style="color: #007800;">tab</span>=wg<br />
&nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>mail.google.com, <span style="color: #000000;">1</span> links<br />
&nbsp; &nbsp; &nbsp; &nbsp; http:<span style="color: #000000; font-weight: bold;">//</span>mail.google.com<span style="color: #000000; font-weight: bold;">/</span>mail<span style="color: #000000; font-weight: bold;">/</span>?<span style="color: #007800;">hl</span>=ja<span style="color: #000000; font-weight: bold;">&amp;</span><span style="color: #007800;">tab</span>=wm<br />
... 以下省略</div></div>
<h4>ウェブアプリでスクレイピング</h4>
<p>上のコマンドラインスクリプトと同じ処理を行うウェブサーバスクリプトも書いてみます。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// server.js</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> hostname <span style="color: #339933;">=</span> <span style="color: #3366CC;">'localhost'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> port <span style="color: #339933;">=</span> <span style="color: #CC0000;">8124</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; ejs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; linkPicker <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./linkPicker'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
app.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.ejs'</span><span style="color: #339933;">,</span> ejs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">query</span> <span style="color: #339933;">&amp;&amp;</span> req.<span style="color: #660066;">query</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; linkPicker.<span style="color: #660066;">pickupLinks</span><span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">query</span>.<span style="color: #660066;">url</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> links<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'403 Forbidden'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">403</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url<span style="color: #339933;">:</span> req.<span style="color: #660066;">query</span>.<span style="color: #660066;">url</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; links<span style="color: #339933;">:</span> links<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sorted<span style="color: #339933;">:</span> linkPicker.<span style="color: #660066;">sortLinksByHost</span><span style="color: #009900;">&#40;</span>links<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url<span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span>port<span style="color: #339933;">,</span> hostname<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>スクリプトでは <a href="http://expressjs.com/">express</a> フレームワークと <a href="https://github.com/visionmedia/ejs">ejs</a> テンプレートエンジンを使用しています。手元に無い場合は npm でインスコしてください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>npm <span style="color: #c20cb9; font-weight: bold;">install</span> express ejs</div></div>
<p>テンプレートエンジン用に、以下の3つのファイルを views サブディレクトリに作ります。</p>
<ul>
<li>views/layout.ejs
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype html&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;UTF-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>node.js example - link picker<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>node.js example - link picker<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;GET&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; Enter URL:<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;url&quot;</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;40&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= url %&gt;</span></span>&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Submit&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%- body %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
</li>
<li>views/index.ejs
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;% <span style="color: #66cc66;">/</span>* empty *<span style="color: #66cc66;">/</span> %&gt;</span></div></div>
</li>
<li>views/result.ejs
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span>Back to the top page<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;&lt;%<span style="color: #66cc66;">=</span> url %&gt;</span> contains <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> links.length %&gt;</span> links<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;% <span style="color: #000066;">for</span> <span style="color: #66cc66;">&#40;</span>var i <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>; i &lt; sorted.hosts.length; ++i<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> %&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;% var host <span style="color: #66cc66;">=</span> sorted.hosts<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>; %&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;&lt;%<span style="color: #66cc66;">=</span> host %&gt;</span> - <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> sorted.hostLinks<span style="color: #66cc66;">&#91;</span>host<span style="color: #66cc66;">&#93;</span>.length %&gt;</span> links<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;% <span style="color: #000066;">for</span> <span style="color: #66cc66;">&#40;</span>var j <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>; j &lt; sorted.hostLinks<span style="color: #66cc66;">&#91;</span>host<span style="color: #66cc66;">&#93;</span>.length; ++j<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> %&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;&lt;%<span style="color: #66cc66;">=</span> sorted.hostLinks<span style="color: #66cc66;">&#91;</span>host<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span>j<span style="color: #66cc66;">&#93;</span>.<span style="color: #000066;">href</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;% <span style="color: #66cc66;">&#125;</span> %&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;% <span style="color: #66cc66;">&#125;</span> %&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span></div></div>
</li>
</ul>
<p>できたらサーバスクリプトを起動します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>node server.js</div></div>
<p>http://localhost:8124/ にブラウザからアクセスするとフォームが表示されます。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/linkpicker1.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/linkpicker1-300x213.png" alt="node.js link picker" width="300" height="213" class="aligncenter size-medium wp-image-3513" /></a></p>
<p>フォームに URL を入力して submit するとスクレイピングします。<br />
<a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/linkpicker2.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/linkpicker2-300x213.png" alt="node.js link picker" width="300" height="213" class="aligncenter size-medium wp-image-3514" /></a></p>
<p>もうちょい改造してデッドリンク検出とかできるようにしようかと思いましたが面倒なので却下ということで。</p>
<p>んでわ。</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/3393/feed</wfw:commentRss>
		<slash:comments>550</slash:comments>
		</item>
		<item>
		<title>新型はてなブックマークボタンを速くする</title>
		<link>http://sakuratan.biz/archives/3068</link>
		<comments>http://sakuratan.biz/archives/3068#comments</comments>
		<pubDate>Sun, 23 Jan 2011 15:37:34 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[はてな]]></category>
		<category><![CDATA[はてブ]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=3068</guid>
		<description><![CDATA[新型はてなブックマークボタン使ってます？ぶっちゃけあんまり見ない気もしますが、↓みたいな感じで thickbox が開いたりして結構便利ですよ！ Twitter とか Facebook のボタンと似たような感じで今風なのも(･∀･)ｲｲ!! つーことで、このブログにも新型はてブボタン置きたいなーと WordPress のテンプレいじくってたりしてたんですが、ブラクラかと思うぐらいに新型はてブボタン... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/3068">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p><a href="http://b.hatena.ne.jp/guide/bbutton">新型はてなブックマークボタン</a>使ってます？ぶっちゃけあんまり見ない気もしますが、↓みたいな感じで thickbox が開いたりして結構便利ですよ！</p>
<p><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/hatenabutton.jpg" alt="はてなブックマークボタン" title="はてなブックマークボタン" width="392" height="364" class="aligncenter size-full wp-image-3347 capture" /></p>
<p>Twitter とか Facebook のボタンと似たような感じで今風なのも(･∀･)ｲｲ!!</p>
<p>つーことで、このブログにも新型はてブボタン置きたいなーと WordPress のテンプレいじくってたりしてたんですが、ブラクラかと思うぐらいに新型はてブボタンが遅かったので、もうちょいキビキビ動くように最適化してみました。</p>
<h3>速くする</h3>
<p>遅い原因も調べてますがとりあえずその辺は後述ということで、先に新型はてブボタンの動作を速くする方法から書いていきます。</p>
<p>まず<a href="http://b.hatena.ne.jp/guide/bbutton">はてブのボタン配信ページ</a>から貼り付けコードを取得します。こんな感じの HTML スニペットがもらえると思います。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.hatena.ne.jp/entry/http://sakuratan.biz&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hatena-bookmark-button&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;data-hatena-bookmark-<span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;さくらたんどっとびーず&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;data-hatena-bookmark-layout<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;standard&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;このエントリーをはてなブックマークに追加&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.st-hatena.com/images/entry-button/button-only.gif&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;このエントリーをはてなブックマークに追加&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;border: none;&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.st-hatena.com/js/bookmark_button.js&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span> async<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;async&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></div>
<p>で、このスニペットをそのまま貼っちゃうと何回かに一回のタイミングでページ表示が超遅くなります。</p>
<p>遅くならないようにするには、a タグ部分をボタンを置きたい箇所に、script タグ部分を HTML ファイルの末尾に分けて貼ります。</p>
<p>a タグ部分はこんな感じ。1ページに何個もはてブボタンを置きたい場合は、置きたい箇所それぞれに a タグのみを記述します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.hatena.ne.jp/entry/http://sakuratan.biz&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hatena-bookmark-button&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;data-hatena-bookmark-<span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;さくらたんどっとびーず&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;data-hatena-bookmark-layout<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;standard&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;このエントリーをはてなブックマークに追加&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.st-hatena.com/images/entry-button/button-only.gif&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;このエントリーをはてなブックマークに追加&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;border: none;&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span></div></div>
<p>script タグは /body の手前あたりに1回だけ記述します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.st-hatena.com/js/bookmark_button.js&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span> async<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;async&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>もしくは jQuery を使っているサイトの場合、script タグを body 末尾に置く代わりに、以下の script タグを head タグに置いてもおkです。こっちの方がコードがスッキリすると思います。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;</span><br />
$(function() {<br />
&nbsp; &nbsp; var script = document.createElement('script');<br />
&nbsp; &nbsp; script.src = 'http://b.st-hatena.com/js/bookmark_button.js';<br />
&nbsp; &nbsp; script.charset = &quot;utf-8&quot;;<br />
&nbsp; &nbsp; script.async = true;<br />
&nbsp; &nbsp; $('body').append(script);<br />
});<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></div>
<p>これで新型はてブボタンを置いたページの表示がたまに超遅くなる現象が回避できると思います。</p>
<h3>何で遅いの？</h3>
<p>と、先に対処方法から説明しましたが、ここからは何で遅いかについて。</p>
<p>とりあえずどこで時間がかかってるのか把握する必要があるので、Firebug とニラメッコしながら新型はてブボタンを何度かリロードしてみたところ、新型ボタンで使ってる JavaScript  の配信サーバ b.st-hatena.com の応答がたまに遅いと分かりました。</p>
<p>そのため<a href="http://b.hatena.ne.jp/guide/bbutton">はてブのボタン配信ページ</a>から配布している HTML スニペットの http://b.st-hatena.com/js/bookmark_button.js の読み込みでブロッキングが発生し、数秒間ページ表示が止まったようになります。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.hatena.ne.jp/entry/http://sakuratan.biz&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;hatena-bookmark-button&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;data-hatena-bookmark-<span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;さくらたんどっとびーず&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;data-hatena-bookmark-layout<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;standard&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;このエントリーをはてなブックマークに追加&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.st-hatena.com/images/entry-button/button-only.gif&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;このエントリーをはてなブックマークに追加&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;20&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;border: none;&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://b.st-hatena.com/js/bookmark_button.js&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span> async<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;async&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></div>
<p>このスニペットでは script タグに async 属性を指定してますが、async 属性は実行が非同期になるだけで、JavaScript ファイルの読み込みに対してはブロッキングが発生します。ブロッキングが発生するとスクリプトの読み込みが完了するまでブラウザのレンダリングが中断されます。なので bookmark_button.js の読み込みが完了するまでブラウザが固まったような状態になります。</p>
<p>新型はてブボタンのスニペットでは b.st-hatena.com から button-only.gif 画像ファイルも読み込んでいますが、img タグはブロッキングしませんので問題となるのは script タグだけです。</p>
<h4>対処方法を考える</h4>
<p>原因が分かりましたのでブラウザから <a href="http://b.st-hatena.com/js/bookmark_button.js">http://b.st-hatena.com/js/bookmark_button.js</a> を開いてあーだこーだソースを読んでいくと、setInterval で class=&#8221;hatena-bookmark-button&#8221; を持つ a タグに iframe を足す処理をポーリングしているのが分かりました。</p>
<p>ポーリングごとに条件を満たす全ての a タグに対してブックマーク数を表示する処理を行っていますので、スニペットの a タグと script タグを分けても問題無さそうです。ということで上の結論となりました。</p>
<p>まあ script タグ部分で発生するブロッキングをページがすべて表示されてから一度だけ発生するように変えただけなのではてブボタンの表示自体が速くなる訳では無いのですが、ページがすべて表示されるまでのイライラがだいぶ解消されると思います。新型置きたい方はぜひお試しを。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// bookmark_button.js のポーリング処理部分あたりの抜粋</span><br />
extend<span style="color: #009900;">&#40;</span>B.<span style="color: #660066;">BookmarkButton</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; interval<span style="color: #339933;">:</span> <span style="color: #CC0000;">428</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">/* Welcome to Shibuya.js! */</span><br />
&nbsp; &nbsp; timerId<span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; setup<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">timerId</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> Button <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">timerId</span> <span style="color: #339933;">=</span> window.<span style="color: #660066;">setInterval</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> Button.<span style="color: #660066;">tryCreate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">interval</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">tryCreate</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; lastLinkCount<span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; tryCreate<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> links <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> linkCount <span style="color: #339933;">=</span> links.<span style="color: #660066;">length</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>linkCount <span style="color: #339933;">===</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastLinkCount</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> buttonLinks <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> classRE <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/(?:^|\s)hatena-bookmark-button(?:\s|$)/</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> linkCount<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>classRE.<span style="color: #660066;">test</span><span style="color: #009900;">&#40;</span>links<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">className</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">!</span>links<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'data-hatena-bookmark-initialized'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buttonLinks.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>links<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> buttonLinks.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">new</span> B.<span style="color: #660066;">BookmarkButton</span><span style="color: #009900;">&#40;</span>buttonLinks<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastLinkCount</span> <span style="color: #339933;">=</span> links.<span style="color: #660066;">length</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/3068/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>node.jsとMySQLで割と普通のデータベースウェブアプリを作ってみるチュートリアル</title>
		<link>http://sakuratan.biz/archives/3101</link>
		<comments>http://sakuratan.biz/archives/3101#comments</comments>
		<pubDate>Sun, 16 Jan 2011 15:52:14 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ejs]]></category>
		<category><![CDATA[express]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=3101</guid>
		<description><![CDATA[2011年はサーバサイド JavaScript の年！ サーバサイド JavaScript の本命は node.js！ ということで割と普通のウェブアプリケーションを node.js で作るためのチュートリアルを書いてみました。WebSocket とか新しめの話題は結構見ますが、PHP とかで普通のウェブアプリ作ってる人向けのチュートリアルとかあんま見ないような気がしたので、って感じです。 チュー... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/3101">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>2011年はサーバサイド JavaScript の年！<br />
サーバサイド JavaScript の本命は node.js！</p>
<p><a href="http://nodejs.org/"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/logo.png" alt="node.js" title="node.js" width="420" height="111" class="aligncenter size-full wp-image-3315" style="background-color:#22252A"/></a></p>
<p>ということで割と普通のウェブアプリケーションを node.js で作るためのチュートリアルを書いてみました。WebSocket とか新しめの話題は結構見ますが、PHP とかで普通のウェブアプリ作ってる人向けのチュートリアルとかあんま見ないような気がしたので、って感じです。</p>
<p>チュートリアルの内容ですが、コード量が少なめで機能的にも分かりやすそうなモノということで、短縮 URL ウェブアプリケーションを作ってみることにしました。bit.ly とか t.co とか nico.ms みたいなアレです。短縮 URL のデータは MySQL に保存します。</p>
<p>結構長文になっちゃったので、先に目次置いときます。</p>
<ol>
<li>node.js のインストール</li>
<li>npm (Node Package Manager) のインストール</li>
<li>express フレームワークの簡単な使い方</li>
<li>ejs テンプレートエンジンを express フレームワークで使う方法</li>
<li>node.js 用 MySQL モジュールの使用例</li>
<li>自作モジュールの作成例</li>
</ol>
<p>チュートリアルを一通り試せば簡単なウェブアプリなら作れるようになるかもしんないので、お暇な方はどうぞ。</p>
<p>あとチュートリアルで作ったソースを固めた ZIP も置いときますので、ソース見た方がはえーって人は ZIP からどうぞ。</p>
<blockquote><p>
<a href='http://sakuratan.biz/blog/wp-content/uploads/2011/01/nodejs-urlshortener.zip'>nodejs-urlshortener.zip</a>
</p></blockquote>
<p>（2011/1/18 21:20）ちろっと正規表現が変だったようで一ヶ所直して ZIP をうpり直しました。<br />
×　/^\/([0-9A-Z]{5,}$)$/<br />
○　/^\/([0-9A-Z]{5,})$/<br />
修正前の正規表現でもちゃんと動いてるので機能的にバグってる訳ではないようですが、Typo ですし $)$ は変な感じです(*´・ω・)(・ω・｀*)ﾈｰ</p>
<h3>node.js のインストール</h3>
<p>とりあえず node.js が無ければ話が始まらないのでとっととインスコしていきます。</p>
<p>node.js のアーカイブは<a href="http://nodejs.org/">公式サイト</a>の<a href="http://nodejs.org/#download">ダウンロード</a>から配布されています。2011年1月10日時点では安定版としてバージョン 0.2.6、開発版としてバージョン 0.3.4 のアーカイブが配布されています。</p>
<p>今んところ開発中の機能が使いたい訳でも無いので安定版をインストールすることにしました。開発版を使う場合はアーカイブのソースを使うよりも、github の <a href="https://github.com/ry/node">node.js のリポジトリ</a>からソースを持ってきた方が良いと思います。</p>
<p>node.js が動く環境ですが<a href="http://nodejs.org/">公式サイト</a>によると Linux、Macintosh、Solaris でテストされているということです。また Windows/Cygwin、FreeBSD、OpenBSD でもだいたい動くとのことです。</p>
<p>さくらの VPS の CentOS と MacBook にインスコしてみたのですが、どちらもインストール作業自体はあっさり簡単に終わりました。インストールする前に必要になるライブラリとかが若干違いますので OS 別にインストール方法を説明します。</p>
<h4>CentOS の場合</h4>
<p>CentOS の場合、node.js をインストールする前に OpenSSL と Python が必要になります。Python を yum 以外の方法でインストールする場合はバージョン 2.4 以降をインストールしてください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">yum install</span> openssl-devel<br />
$ <span style="color: #c20cb9; font-weight: bold;">yum install</span> python</div></div>
<p>OpenSSL と Python がインストールできたら <a href="http://nodejs.org/#build">ビルド方法の説明</a> に従って node.js をインストールします。make install は root で実行してください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">tar</span> xvzf node-v0.2.6.tar.gz<br />
$ <span style="color: #7a0874; font-weight: bold;">cd</span> node-v0.2.6<br />
$ .<span style="color: #000000; font-weight: bold;">/</span>configure<br />
$ <span style="color: #c20cb9; font-weight: bold;">make</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></div>
<p>ビルド／インストールはすぐ終わると思います。</p>
<p>インストールが完了すると /usr/local/bin/node に node.js のバイナリがインストールされます。インストール先を変更したい場合は configure 実行時に &#8211;prefix=DIR オプションを指定してください。その他のビルド／インストールオプションについては、configure &#8211;help で参照してください。</p>
<h4>Mac OS X の場合</h4>
<p>Mac OS X の場合、コンパイルするのに GNU C コンパイラ (GCC) が必要になります。GCC は Xcode からインストールするのが良いと思います。Xcode のインストール方法は <a href="http://osksn2.hep.sci.osaka-u.ac.jp/~taku/osx/install_xcode.html">このページ</a>等を参考にしてください。（ポックンの MacBook、iPhone の SDK 入れたときに Xcode 入れちゃったので、インストール手順覚えとらんので説明できんとです。サーセン）</p>
<p>Mac OS X には Python は元からインストールされていますので Xcode 以外のインストールは不要です。</p>
<p>node.js のビルド／インストールは、CentOS の場合と同じように configure / make で行います。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">tar</span> xvzf node-v0.2.6.tar.gz<br />
$ <span style="color: #7a0874; font-weight: bold;">cd</span> node-v0.2.6<br />
$ .<span style="color: #000000; font-weight: bold;">/</span>configure<br />
$ <span style="color: #c20cb9; font-weight: bold;">make</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></div>
<p>node.js には Mac OS X 用パッケージを作るためのスクリプトが tools/osx-dist.sh に用意されているのですが、後述する npm と設定が一致していないため使わない方が良いと思います。</p>
<h3>npm (Node Package Manager) のインストール</h3>
<p>npm (Node Package Manager) は node.js の CPAN みたいなもので外部モジュールのインストールに使います。</p>
<p>npm のインストール用スクリプトが http://npmjs.org/install.sh にありますので、ダウンロードして実行します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>curl http:<span style="color: #000000; font-weight: bold;">//</span>npmjs.org<span style="color: #000000; font-weight: bold;">/</span>install.sh <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sh</span></div></div>
<p>ただまあこれ、そのまま一般ユーザーで動かすとディレクトリにパーミッションが無いエラーで異常終了します。</p>
<p>node.js と同じ /usr/local 以下にファイルを置こうとしてるので当然と言えば当然ですが、<a href="https://github.com/isaacs/npm/issues/issue/294">npm 自体がこの辺の仕様を固めきっていないみたい</a>ですのでアレコレ…</p>
<p>どこから説明したら良いものか悩みますが、<a href="https://github.com/isaacs/npm/blob/master/doc/developers.md#readme">npm のリポジトリには誰でもパッケージをアップロードできる</a>ので、root で npm をインストールする環境だとセキュリティホールになるようなパッケージもアップロードできたりしちゃうのですが、npm の作者さん的には誰でもパッケージメンテナになれる状態を保っておきたいので、npm 自体や npm パッケージを root 権限でインストールしない方がいいよ、ということらしいです。自分で書いてて変な日本語ww</p>
<p><a href="https://github.com/isaacs/npm">isaacs / npm</a> に root 権限なしでインストールする方法が何個か説明されてますが、ポックン的にはリスクは把握しましたし、Your own risk とか *NIX だと割と当たり前なんで sudo でインスコすることにしました。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>curl http:<span style="color: #000000; font-weight: bold;">//</span>npmjs.org<span style="color: #000000; font-weight: bold;">/</span>install.sh <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">sh</span></div></div>
<p>心配な人は <a href="https://github.com/isaacs/npm">isaacs / npm</a> に従って root 権限なしでインスコするか、<a href="https://gist.github.com/579814">https://gist.github.com/579814</a> の説明に従って ~/local とかに npm をインスコするのが良いと思います。</p>
<p>なお npm を sudo でインスコした場合、npm でパッケージをインスコする際も root で実行する必要があります。root でパッケージをインスコすると npm がワーニングを出しますがとりあえず無視です。</p>
<p>あとこの辺は、もうじき仕組みが変わる予定だそうです。変わった後でこのブログ見た人は上の説明を無視してください。</p>
<blockquote><p>
It is on the roadmap to make npm do a bunch of chown/setuid stuff when sudoed, so eventually it&#8217;ll actually be safer to run as root than as a user account, but that&#8217;s a refactor that is slowly progressing.<br />
<cite><a href="https://github.com/isaacs/npm">https://github.com/isaacs/npm</a></cite>
</p></blockquote>
<h4>モジュールのインストール</h4>
<p>npm がインスコできたらモジュールをインスコしていきます。</p>
<p>今回のチュートリアルでは、<a href="https://github.com/felixge/node-mysql">node-mysql</a> (MySQL)、<a href="http://expressjs.com/">express</a> (express フレームワーク)、<a href="https://github.com/visionmedia/ejs">ejs</a> (テンプレートエンジン) を使います。</p>
<p>モジュールのインストールは npm install コマンドで行います。npm を sudo でインスコした場合は、npm install は root で実行してください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ npm <span style="color: #c20cb9; font-weight: bold;">install</span> mysql<br />
$ npm <span style="color: #c20cb9; font-weight: bold;">install</span> express<br />
$ npm <span style="color: #c20cb9; font-weight: bold;">install</span> ejs</div></div>
<p>あと mysql モジュールをインストールする前に MySQL 本体をインスコしておいてください。本筋と関係無いので MySQL のインスコ方法は省略します。</p>
<h3>node.js を試してみる</h3>
<p>インストールが終わったら早速 node.js を動かしてみます。</p>
<p>最初は <a href="http://nodejs.org/">node.js 公式サイト</a>のサンプルコードを動かしてみます。このサンプルはウェブサーバを起動し、HTTP 経由のアクセスに対して Hello World を返します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// モジュールの読み込み</span><br />
<span style="color: #003366; font-weight: bold;">var</span> http <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// サーバを起動する</span><br />
http.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">writeHead</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'Content-Type'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'text/plain'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Hello World<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8124</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;127.0.0.1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Server running at http://127.0.0.1:8124/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>↑のソースをコピペして適当なディレクトリに example.js として保存します。ターミナルから node コマンドを実行して node.js を起動します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ node example.js<br />
Server running at http:<span style="color: #000000; font-weight: bold;">//</span>127.0.0.1:<span style="color: #000000;">8124</span></div></div>
<p>Server running &#8230; メッセージが出力されていれば起動に成功しています。ブラウザや wget / curl 等で http://127.0.0.1:8124 にアクセスすると HTTP レスポンスが返されます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ curl http:<span style="color: #000000; font-weight: bold;">//</span>127.0.0.1:<span style="color: #000000;">8124</span><br />
Hello World</div></div>
<h3>ファイルを読み込んで表示</h3>
<p>上の Node.js のサンプルではプログラムから直接コンテンツを出力していましたが、メンテとかめんどそうなのでファイルからコンテンツを読み込んで出力するように改造します。</p>
<p>ファイル入出力には fs モジュールを使います。fs モジュールは Node.js 本体に含まれています。</p>
<p>fs.readFile 関数を使い index.html を読み込み出力するように改造した example.js です。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// fsモジュールも読み込む</span><br />
<span style="color: #003366; font-weight: bold;">var</span> http <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
http.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// index.html を読み込んで表示</span><br />
&nbsp; &nbsp; fs.<span style="color: #660066;">readFile</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.html'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> content<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">writeHead</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'Content-Type'</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'text/html; charset=utf-8'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span>content<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8192</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'127.0.0.1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>index.html の中身はこんな感じで、JavaScript と同じディレクトリに置きます。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype HTML&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;UTF-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;POST&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; Enter URL: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;url&quot;</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;50&quot;</span> <span style="color: #000066;">maxlength</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;256&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Submit&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>両方できたら先ほどと同じようにサーバを起動します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>node example.js</div></div>
<h4>非同期 I/O</h4>
<p>node.js でプログラムを書く場合、入出力は基本的に非同期 I/O を使います。上の例では fs.readFile を使用していますが、readFile はファイルの読み込みを完了するとエラーとファイルの中身を引数にコールバック関数を呼び出します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">fs.<span style="color: #660066;">readFile</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.html'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> content<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// 読み込み完了時に呼び出される</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>コールバック関数の引数には、読み込み成功時は null と読み込んだコンテンツが、失敗時はそのまま例外送出可能なエラーオブジェクトが渡されます。</p>
<p>非同期 I/O とは I/O 関数呼び出し時にブロッキングしないことを意味します。上と似たようなコードを PHP で書くと以下のようになりますが、file_get_contents はコンテンツの読み込みが完了するまでプロセスの実行をブロッキングします。</p>
<div class="codecolorer-container php dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'index.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Apache などのマルチプロセス（マルチスレッド）サーバでは、複数のプロセスでリクエスト応答を行います。サーバプロセス上で実行されるスクリプトでブロッキングが発生すると、そのプロセスの実行は単純に中断されます。中断中は他のサーバプロセスが他のリクエストの応答を行います。</p>
<p>一方 node.js はシングルプロセスウェブサーバですので、I/O 要求等によるブロッキングが発生するとサーバ全体の動作が中断してしまいます。もちろんそれではサーバとして用を成さないので、非同期 I/O を使って I/O 要求を発生時に別の実行可能な処理へサーバの処理を切り替えます。</p>
<p>Apache 上で普通の（同期 I/O を使った）スクリプトを書く方が簡単そうですが（実際に簡単ですけど）、node.js が注目された背景には <a href="http://www.hyuki.com/yukiwiki/wiki.cgi?TheC10kProblem">C10k 問題</a> があり、10000 (10k) を超えるクライアント接続に従来の（マルチプロセス／マルチスレッド型）ウェブサーバでは耐えられなくなってきたので、単一プロセス非同期 I/O ウェブサーバが必要とされている現状があります。</p>
<p>node.js というとサーバサイド JavaScript により学習コストの低下を期待する向きもあると思いますが、（非同期 I/O を使ってる関係で）ちょっとしたコーディングミスがサーバ全体の性能に影響を与える場合もありますのでプログラミングには注意が必要です。</p>
<h3>express フレームワークを使う</h3>
<p>小難しい話はこの辺にして、node.js 本体に含まれるモジュールだけでコーディングしているとソースが長ったらしくなるので、<a href="http://expressjs.com/">express フレームワーク</a>を使うようにソースを書き換えます。</p>
<p>先ほどまで全然説明していませんでしたが、モジュールの読み込みには require 関数を使います。require はモジュールオブジェクトを返します。モジュールオブジェクトは変数に代入して使用するのが一般的です。</p>
<p>express フレームワークでは、express.createServer でサーバオブジェクトを作成し、サーバオブジェクトの get メソッド等で URL マッパを設定します。以下の例ではサーバルート (/) へのリクエストに対し、sendfile でファイルの中身をレスポンスします。（上の例と同じ処理です。）</p>
<p>以下が修正したソースです。ついでにファイル名も変えます。server.js として保存してください。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// モジュールの読み込み</span><br />
<span style="color: #003366; font-weight: bold;">var</span> express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// サーバを作成</span><br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// '/' のリクエストハンドラ</span><br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">sendfile</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// サーバを起動</span><br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8124</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'127.0.0.1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h3>POST パラメータの処理と ejs テンプレート</h3>
<p>index.html からは HTTP POST でフォームデータを送信しますので、そのリクエストハンドラを記述していきます。</p>
<p>express で POST メソッドのリクエストハンドラを記述する場合、サーバオブジェクトの post メソッドで URL マッパを設定します。</p>
<p>HTTP 経由で受け取ったパラメータは、POST の場合は req.body にオブジェクトとして渡されます。あらかじめ app.use(express.bodyDecoder()) を呼び出しておかないと POST パラメータは処理してくれないので注意してください。</p>
<p>あとこのチュートリアルでは使ってませんが、URL の QueryString （PHP の $_GET） は req.query に渡されます。</p>
<p>また HTML コンテンツにデータを埋め込むため、<a href="https://github.com/visionmedia/ejs">ejs テンプレートエンジン</a>を使用するように変更します。ejs の 他に <a href="http://jade-lang.com/">Jade</a>、<a href="http://github.com/visionmedia/haml.js">Haml</a>、<a href="https://github.com/mauricemach/coffeekup">CoffeeKup</a>、<a href="https://github.com/kof/node-jqtpl">jQuery Templates</a> などのテンプレートエンジンも express と連動可能です。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// ejs モジュールも読み込む</span><br />
<span style="color: #003366; font-weight: bold;">var</span> express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; ejs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// bodyDecoder を指定しないと express が POST パラメータを処理してくれない</span><br />
app.<span style="color: #003366; font-weight: bold;">use</span><span style="color: #009900;">&#40;</span>express.<span style="color: #660066;">bodyDecoder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// app.render('*.ejs') は ejs テンプレートエンジンで処理させる</span><br />
app.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.ejs'</span><span style="color: #339933;">,</span> ejs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ejs テンプレートエンジンでレンダリング</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// req.body に POST パラメータがセットされるので</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// そのままテンプレートに渡す</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> message<span style="color: #339933;">:</span> req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span> <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8124</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'127.0.0.1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>テンプレートファイルは views サブディレクトリに配置します。views サブディレクトリにはページレイアウトを定義する layout.ejs が必要です。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype HTML&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;UTF-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%- body %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>views/index.ejs には先ほどの index.html の form 部分を記述します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;POST&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span><br />
&nbsp; Enter URL: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;url&quot;</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;50&quot;</span> <span style="color: #000066;">maxlength</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;256&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Submit&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></div>
<p>views/result.ejs には message 置換変数を配置します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;&lt;%<span style="color: #66cc66;">=</span> message %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span></div></div>
<p>ejs では &lt;%= varname %> が html エスケープ付きのテンプレート変数出力、&lt;%- varname %> がエスケープなしの変数出力です。&lt;% code %> で JavaScript コードを直接記述することもできます。詳しくは <a href="https://github.com/visionmedia/ejs">https://github.com/visionmedia/ejs</a> をご覧ください。</p>
<h3>MySQL との連動</h3>
<p>今回のウェブアプリではテーブル短縮 URL 変換用テーブルをデータベースに保持します。テーブル定義はこんな感じです。</p>
<p>mysql コマンド等で予めデータベースに作成します。</p>
<div class="codecolorer-container sql dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> shorten_urls<br />
<span style="color: #66cc66;">&#40;</span>id &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">BIGINT</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span><br />
&nbsp;long_url &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">256</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">COLLATE</span> utf8_bin<span style="color: #66cc66;">&#41;</span>;</div></div>
<p>node.js から MySQL データベースへ問い合わせを行うには、mysql モジュールの Client ライブラリを使用します。データベース問い合わせも I/O ですので非同期です。</p>
<p>以下が最終的に完成した短縮 URL ウェブアプリケーションプログラムです。base62 モジュールについては後述します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// サーバのアドレスとポート</span><br />
<span style="color: #003366; font-weight: bold;">var</span> HOSTNAME <span style="color: #339933;">=</span> <span style="color: #3366CC;">'localhost'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> PORT <span style="color: #339933;">=</span> <span style="color: #CC0000;">8124</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// MySQL データベース名、ユーザー名、パスワード</span><br />
<span style="color: #003366; font-weight: bold;">var</span> DBNAME <span style="color: #339933;">=</span> <span style="color: #3366CC;">'nodejs_url_shortener'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> DBUSER <span style="color: #339933;">=</span> <span style="color: #3366CC;">'root'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> DBPASSWD <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sys'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; ejs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; Client <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mysql'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Client</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; base62 <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./base62'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// MySQLデータベースに接続しcallbackを呼び出す</span><br />
<span style="color: #003366; font-weight: bold;">function</span> mysql<span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> client <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Client<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">database</span> <span style="color: #339933;">=</span> DBNAME<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">user</span> <span style="color: #339933;">=</span> DBUSER<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">password</span> <span style="color: #339933;">=</span> DBPASSWD<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; client.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>client<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
app.<span style="color: #003366; font-weight: bold;">use</span><span style="color: #009900;">&#40;</span>express.<span style="color: #660066;">bodyDecoder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
app.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.ejs'</span><span style="color: #339933;">,</span> ejs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// ルート GET</span><br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// ルート POST</span><br />
app.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// テンプレート変数</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> locals <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; error<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; short_url<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// パラメータをチェック</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">error</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'Missing url parameter'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp;<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">256</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">error</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'url parameter too long'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>locals.<span style="color: #660066;">error</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> locals<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// idを短縮URLに変換して出力</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span> render_short_url<span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">short_url</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'http://'</span> <span style="color: #339933;">+</span> HOSTNAME<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>PORT <span style="color: #339933;">!=</span> <span style="color: #CC0000;">80</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">short_url</span> <span style="color: #339933;">+=</span> <span style="color: #3366CC;">':'</span> <span style="color: #339933;">+</span> PORT<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">short_url</span> <span style="color: #339933;">+=</span> <span style="color: #3366CC;">'/'</span> <span style="color: #339933;">+</span> base62.<span style="color: #660066;">int_to_base62_string</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> locals<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// データベースに短縮URLを登録して表示</span><br />
&nbsp; &nbsp; mysql<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>client<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'INSERT INTO shorten_urls (long_url) VALUES (?)'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#91;</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// キー重複は無視</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err <span style="color: #339933;">&amp;&amp;</span> err.<span style="color: #660066;">number</span> <span style="color: #339933;">!=</span> Client.<span style="color: #660066;">ERROR_DUP_ENTRY</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// インサート成功</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; render_short_url<span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">insertId</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// インサート失敗時はlong_urlをキーで検索する</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'SELECT id FROM shorten_urls WHERE long_url = ?'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#91;</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> <span style="color: #003366; font-weight: bold;">new</span> Error<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Something wrong'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; render_short_url<span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// 短縮URLをリダイレクト</span><br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^\/([0-9A-Z]{5,})$/</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; mysql<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>client<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// idからurlを検索してリダイレクト</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'SELECT long_url FROM shorten_urls WHERE id = ?'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#91;</span>base62.<span style="color: #660066;">base62_string_to_int</span><span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">params</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// データが無い</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Not Found'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">404</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">redirect</span><span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">long_url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span>PORT<span style="color: #339933;">,</span> HOSTNAME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>短縮 URL を展開する際、URL に埋め込まれた ID を正規表現でパースして req.params 経由で受け取ります。この辺は express の機能を使ってますので、詳しくは express のマニュアルの <a href="http://expressjs.com/guide.html#Routing">Routing</a> の項をご覧ください。</p>
<p>コードの修正が終わったら、result.ejs はエラーメッセージも埋め込めるように少し修正します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;% if <span style="color: #66cc66;">&#40;</span>error<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;&lt;%<span style="color: #66cc66;">=</span> error %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<span style="color: #009900;">&lt;% <span style="color: #66cc66;">&#125;</span> else <span style="color: #66cc66;">&#123;</span> %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;</span>Short url is <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= short_url %&gt;</span></span>&quot;&gt;<span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> short_url %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<span style="color: #009900;">&lt;% <span style="color: #66cc66;">&#125;</span> %&gt;</span></div></div>
<p><a href="https://github.com/visionmedia/ejs">ejs</a> テンプレートエンジンでは、&lt;% %> 内に JavaScript のコードをそのまま記述できます。</p>
<h4>mysql モジュールの使い方</h4>
<p>MySQL データベースへの問い合わせは、mysql モジュールの Client クラスを使用して行います。</p>
<p>データベース問い合わせも I/O ですので非同期で実行します。データベース接続やクエリが完了した際に実行される処理をコールバック関数で指定します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> Client <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mysql'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Client</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> client <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Client<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// 接続先データベースを指定</span><br />
client.<span style="color: #660066;">database</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'DB'</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">user</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'USER'</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">password</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'PASSWORD'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// データベースへ接続する</span><br />
client.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// クエリを実行する</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SELECT * FROM T WHERE var = ?&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #003366; font-weight: bold;">var</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>connect メソッドのコールバック関数には、接続成功時は null が、失敗時は例外送出可能なエラーオブジェクトが渡されます。</p>
<p>query メソッドの引数は SQL、バインド変数、コールバック関数です。バインド変数とコールバック関数はそれぞれ省略可能ですので、以下のコードはすべて有効です。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SQL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SQL&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #003366; font-weight: bold;">var</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SQL&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>query メソッドのコールバック関数の引数は、SQL が SELECT の場合は function(err, results, fields) となります。SELECT 以外の場合は function(err, fields) です。</p>
<p>SELECT の場合も SELECT 以外の場合も、err には SQL 実行成功時 は null が、失敗時は例外送出可能なエラーオブジェクトが渡されます。</p>
<p>results は SELECT された列の配列です。配列の要素は列名をキーに持つオブジェクトです。SELECT 時の fields には SELECT された列定義が返されます。</p>
<p>SELECT 以外の場合、fields には affectedRows や insertId など SQL の実行結果を表す情報が渡されます。</p>
<p>MySQL モジュールの API の詳細については、<a href="https://github.com/felixge/node-mysql">https://github.com/felixge/node-mysql</a> をご覧ください。</p>
<h4>非同期コードでの例外処理</h4>
<p>非同期で実行される箇所で例外を送出する場合は注意が必要です。このように単純に例外を送出するとサーバが終了します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;sql...&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>サーバを終了させずにユーザーにエラーを表示する場合は、例外ではなく普通にコンテンツを表示します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;sql...&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Not Found'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">404</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>express には例外送出によりエラー出力をフックするための仕組みが app.error() として用意されていますが、非同期部分から例外を送出してもこの仕組みで補足されませんので例外によらず直接エラー出力を行う必要があるようです。</p>
<h3>自作モジュール</h3>
<p>完成したウェブアプリケーションでは、短縮 URL の id 部分に、base62 の数値を 0-9a-zA-Z で文字列表現するモジュールを使用していますが、このモジュールは自作したものです。（機能的に分けただけで npm からインスコできる形のモジュールではありません。）</p>
<p>自作モジュールのロードも require で行いますが、モジュール名に ./ を付けて require(&#8216;./base62&#8242;) とすることでモジュール検索パスを無効にしています。</p>
<p>モジュールは普通の JavaScript ファイルとして作成します。require では拡張子を省略していますので、base62 モジュールのファイル名は base62.js です。</p>
<p>モジュールから外部へエクスポートするシンボルは、exports の要素にします。base62 モジュールでは int_to_base62_string と base62_string_to_int 関数をエクスポートします。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> base62_map <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; int_map <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> String<span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; base62_map.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> x<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> <span style="color: #3366CC;">'a'</span>.<span style="color: #660066;">charCodeAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">26</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> String.<span style="color: #660066;">fromCharCode</span><span style="color: #009900;">&#40;</span>a <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; base62_map.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> x<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> A <span style="color: #339933;">=</span> <span style="color: #3366CC;">'A'</span>.<span style="color: #660066;">charCodeAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">26</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> String.<span style="color: #660066;">fromCharCode</span><span style="color: #009900;">&#40;</span>A <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; base62_map.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> x<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
exports.<span style="color: #660066;">int_to_base62_string</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>num<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ret <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>num <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">=</span> base62_map<span style="color: #009900;">&#91;</span>num <span style="color: #339933;">%</span> <span style="color: #CC0000;">62</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> ret<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; num <span style="color: #339933;">=</span> parseInt<span style="color: #009900;">&#40;</span>num <span style="color: #339933;">/</span> <span style="color: #CC0000;">62</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> head <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> n <span style="color: #339933;">=</span> <span style="color: #CC0000;">5</span> <span style="color: #339933;">-</span> ret.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> n <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> <span style="color: #339933;">--</span>n<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; head <span style="color: #339933;">+=</span> <span style="color: #3366CC;">'0'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>head<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">=</span> head <span style="color: #339933;">+</span> ret<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
exports.<span style="color: #660066;">base62_string_to_int</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ret <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> str.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> str.<span style="color: #660066;">substr</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">*=</span> <span style="color: #CC0000;">62</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">+=</span> int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>アプリを動かしてみる</h3>
<p>完成したので短縮URLウェブアプリを動かしてみます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>node server.js</div></div>
<p>サーバが起動したらブラウザで <a href="http://localhost:8124">http://localhost:8124</a> にアクセスします。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node1.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node1-300x180.png" alt="URL Shortener" title="URL Shortener" target="_blank" width="300" height="180" class="aligncenter size-medium wp-image-3296 capture" /></a></p>
<p>短縮したい URL を入力して submit を押すと URL が短縮されます。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node2.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node2-300x180.png" alt="URL Shortener" title="URL Shortener" target="_blank" width="300" height="180" class="aligncenter size-medium wp-image-3302 capture" /></a></p>
<p>そのまま短縮された URL をクリックすると元の URL にリダイレクトします。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/google.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/google-300x180.png" alt="google" title="google" target="_blank" width="300" height="180" class="aligncenter size-medium wp-image-3300 capture" /></a></p>
<p>チュートリアルは以上です。</p>
<p>最近の流行りは XMLHttpRequest や jsonp とか使った Facebook の BigPipe みたいな感じのウェブアプリだと思いますので、上で作ったようなちょいと古めのウェブアプリを node.js で作りたいかと聞かれたら答えは明らかに NO ですが、node.js の仕組みを覚えるにはこんな感じの簡単なものから入るのがよろしいんじゃないかと思います。</p>
<p>個人的には今のところ node.js を使う予定はありませんが、どうせ覚えるなら早めの方がよろしいんじゃないでしょうか。</p>
<p>んでわ</p>
<p>P.S. ずっと Node.js だと思い込んでたもんで最初先頭大文字で表記してたんですが、よく見りゃ node.js だったので後から直しました。キャプチャとかソース中の表記は直すのめんどいんで Node.js のままにしてます。サーセン</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/3101/feed</wfw:commentRss>
		<slash:comments>1033</slash:comments>
		</item>
		<item>
		<title>サーバサイドJavaScriptとjQueryでスクレイピング</title>
		<link>http://sakuratan.biz/archives/2972</link>
		<comments>http://sakuratan.biz/archives/2972#comments</comments>
		<pubDate>Fri, 07 Jan 2011 16:06:46 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[env-js]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Rhino]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=2972</guid>
		<description><![CDATA[jQuery でスクレイピングできたらセレクタ使えるし便利かなーと思ったりしたんですが、Rhino と env-js を使うと超簡単にできたのでレポートしてみます。 Rhino と env-js って何ぞい？ Rhino ってのは Java で書かれた JavaScript エンジンです。Rhino を使うとコマンドラインから JavaScript を実行できます。 Rhino には DOM が無... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/2972">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>jQuery でスクレイピングできたらセレクタ使えるし便利かなーと思ったりしたんですが、<a href="https://developer.mozilla.org/ja/Rhino">Rhino</a> と <a href="http://github.com/thatcher/env-js/">env-js</a> を使うと超簡単にできたのでレポートしてみます。</p>
<h3>Rhino と env-js って何ぞい？</h3>
<p><a href="https://developer.mozilla.org/ja/Rhino">Rhino</a> ってのは Java で書かれた JavaScript エンジンです。Rhino を使うとコマンドラインから JavaScript を実行できます。</p>
<p>Rhino には DOM が無いので単体では jQuery を実行することはできませんが、<a href="http://github.com/thatcher/env-js/">env-js</a> という DOM ライブラリを使用するとこの辺はクリアできます。</p>
<p>env-js の中に jQuery を使ったサンプルがいくつか入ってますので、Java とか JavaScript とか詳しい方はそちらを見てもらった方が早いと思います。</p>
<h3>使ってみる</h3>
<p>まず env-js をビルドしないといけないのでその辺の手順から説明します。</p>
<p>とりあえず Rhino は Java で書かれてますので、動かすのに Java が要ります。あと env-js をコンパイルするのに ant が必要です。持ってなかったら以下のリンクからダウンロードして適当にインスコしてください。</p>
<ul>
<li><a href="http://www.java.com/ja/">Java6</a></li>
<li><a href="http://ant.apache.org/">ant</a></li>
</ul>
<p>インスコしたら github から <a href="http://github.com/thatcher/env-js/">env-js</a> を clone し、Rhino 用の env-js をコンパイルします。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">git clone</span> https:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>thatcher<span style="color: #000000; font-weight: bold;">/</span>env-js.git<br />
$ <span style="color: #7a0874; font-weight: bold;">cd</span> env-js<br />
$ ant<br />
Buildfile: build.xml<br />
...</div></div>
<p>ant の実行が終わると、dist/env.rhino.js というのができます。これが Rhino 用の env-js です。</p>
<p>env-js には Rhino 本体と jQuery が添付されています。rhino/js.jar が Rhino、plugins/jquery.js が jQuery です。</p>
<p>env-js のソースツリーのまま使っても問題ありませんが、説明がややこしいので実行に必要なファイルを全部どこか適当なディレクトリにコピーします。実際にスクレイピングする際はこの辺はよしなにしてください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> WHERE<br />
<span style="color: #c20cb9; font-weight: bold;">cp</span> dist<span style="color: #000000; font-weight: bold;">/</span>env.rhino.js rhino<span style="color: #000000; font-weight: bold;">/</span>js.jar plugins<span style="color: #000000; font-weight: bold;">/</span>jquery.js WHERE<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> WHERE</div></div>
<p>以上で準備は終わりです。早速 jQuery でサーバサイドスクレイピングしてみましょう。</p>
<h3>動かしてみる</h3>
<p>大筋を理解するために簡単な HTML をスクレイピングするコードを書いてみます。</p>
<p>まず HTML はこれ。exam1.html として保存してください。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">http-equiv</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Content-Type&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/html;charset=utf-8&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://www.google.co.jp/&quot;</span>&gt;</span>Google<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://www.yahoo.co.jp/&quot;</span>&gt;</span>Yahoo<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>次に exam1.html をスクレイピングする JavaScript です。exam1.js として保存してください。</p>
<p>JavaScript では HTML ファイルから a タグを読み込み (a タグのテキスト, URL) の並びで CSV に出力しています。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// exam1.js</span><br />
<span style="color: #006600; font-style: italic;">// importPackage で Rhino から Java のクラスを直接使える</span><br />
importPackage<span style="color: #009900;">&#40;</span>java.<span style="color: #660066;">io</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// env-js と jQuery をロード</span><br />
load<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'env.rhino.js'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
load<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jquery.js'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// exam1.html を読み込む</span><br />
window.<span style="color: #660066;">location</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'exam1.html'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// document.ready を手動で起動する必要あり</span><br />
jQuery.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// $('a') を CSV にして exam1.txt へ出力する</span><br />
<span style="color: #003366; font-weight: bold;">var</span> out <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> PrintWriter<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> OutputStreamWriter<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">new</span> FileOutputStream<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;exam1.txt&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;UTF-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; out.<span style="color: #660066;">println</span><span style="color: #009900;">&#40;</span>obj.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">','</span> <span style="color: #339933;">+</span> obj.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
out.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>exam1.html、exam1.js ともに env.rhino.js とかと同じディレクトリに置いてください。できたら動かしてみます。</p>
<p>Rhino は直接実行可能な jar ファイルになっていますので、以下のように java から起動できます。起動する際、LANG 環境変数に適切な文字コードをセットしておかないと Java の文字コード変換ルーチンがちゃんと動かないようなので注意してください。</p>
<p>あと Rhino を起動する際に、コマンドライン引数で実行する JavaScript ファイルを指定できるらしいのですが、手元の環境だとそのやり方では起動時にエラーが出ましたので load() を使ってスクリプトを起動しています。この辺の問題が無い環境の方は、コマンドラインから動かした方が便利だと思います。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">env</span> <span style="color: #007800;">LANG</span>=ja_JP.UTF-<span style="color: #000000;">8</span> java <span style="color: #660033;">-jar</span> js.jar<br />
Rhino <span style="color: #000000;">1.7</span> release <span style="color: #000000;">2</span> <span style="color: #000000;">2009</span> 03 <span style="color: #000000;">22</span><br />
js<span style="color: #000000; font-weight: bold;">&gt;</span> load<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">'exam1.js'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;<br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> &nbsp;Envjs<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.6</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>Rhino; U; Linux i386 2.4.18; en-US; rv:1.7.0.rc2<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp;Resig<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">20070309</span> PilotFish<span style="color: #000000; font-weight: bold;">/</span>1.2.35 &nbsp;<span style="color: #7a0874; font-weight: bold;">&#93;</span><br />
js<span style="color: #000000; font-weight: bold;">&gt;</span> quit<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;<br />
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> exam1.txt<br />
Google,http:<span style="color: #000000; font-weight: bold;">//</span>www.google.co.jp<span style="color: #000000; font-weight: bold;">/</span><br />
Yahoo,http:<span style="color: #000000; font-weight: bold;">//</span>www.yahoo.co.jp<span style="color: #000000; font-weight: bold;">/</span><br />
$</div></div>
<p>とりあえず CSV はちゃんとできてるようです。</p>
<h3>もう少し本格的に</h3>
<p>ローカルのファイルをスクレイピングしてもあんまりうれしくないので、Google の検索結果をスクレイピングしてみることにします。</p>
<p>といっても基本の部分は先ほどのコードでほとんどできあがってまして、window.location を Google 検索の URL に変えて、jQuery のセレクタを Google の検索結果に合わせて書き換えればできあがりです。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// exam2.js</span><br />
importPackage<span style="color: #009900;">&#40;</span>java.<span style="color: #660066;">io</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
load<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'env.rhino.js'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
load<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'jquery.js'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
window.<span style="color: #660066;">location</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'http://www.google.co.jp/search?q=AAA&amp;ie=utf-8&amp;oe=utf-8'</span><span style="color: #339933;">;</span><br />
jQuery.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> out <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> PrintWriter<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> OutputStreamWriter<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">new</span> FileOutputStream<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;exam2.txt&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;UTF-8&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#ires li.g a.l'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; out.<span style="color: #660066;">println</span><span style="color: #009900;">&#40;</span>obj.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">','</span> <span style="color: #339933;">+</span> obj.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
out.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>スクレイピングするコードは正規表現がグっちゃらグっちゃらになってることが多いと思いますが、jQuery を使うとすごいすっきりしたコードになっていい感じです。</p>
<p>スクリプトができたら exam1.js と同じように実行します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">env</span> <span style="color: #007800;">LANG</span>=ja_JP.UTF-<span style="color: #000000;">8</span> java <span style="color: #660033;">-jar</span> js.jar<br />
Rhino <span style="color: #000000;">1.7</span> release <span style="color: #000000;">2</span> <span style="color: #000000;">2009</span> 03 <span style="color: #000000;">22</span><br />
js<span style="color: #000000; font-weight: bold;">&gt;</span> load<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">'exam2.js'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;<br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> &nbsp;Envjs<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1.6</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>Rhino; U; Linux i386 2.4.18; en-US; rv:1.7.0.rc2<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp;Resig<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">20070309</span> PilotFish<span style="color: #000000; font-weight: bold;">/</span>1.2.35 &nbsp;<span style="color: #7a0874; font-weight: bold;">&#93;</span><br />
js<span style="color: #000000; font-weight: bold;">&gt;</span> quit<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;<br />
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> exam2.txt<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.avexnet.or.jp<span style="color: #000000; font-weight: bold;">/</span>aaa<span style="color: #000000; font-weight: bold;">/</span>index.html,AAA（トリプル・エー）OFFICIAL WEBSITE<br />
http:<span style="color: #000000; font-weight: bold;">//</span>ja.wikipedia.org<span style="color: #000000; font-weight: bold;">/</span>wiki<span style="color: #000000; font-weight: bold;">/</span>AAA_<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">%</span>E9<span style="color: #000000; font-weight: bold;">%</span>9F<span style="color: #000000; font-weight: bold;">%</span>B3<span style="color: #000000; font-weight: bold;">%</span>E6<span style="color: #000000; font-weight: bold;">%</span>A5<span style="color: #000000; font-weight: bold;">%</span>BD<span style="color: #000000; font-weight: bold;">%</span>E3<span style="color: #000000; font-weight: bold;">%</span>82<span style="color: #000000; font-weight: bold;">%</span>B0<span style="color: #000000; font-weight: bold;">%</span>E3<span style="color: #000000; font-weight: bold;">%</span>83<span style="color: #000000; font-weight: bold;">%</span>AB<span style="color: #000000; font-weight: bold;">%</span>E3<span style="color: #000000; font-weight: bold;">%</span>83<span style="color: #000000; font-weight: bold;">%</span>BC<span style="color: #000000; font-weight: bold;">%</span>E3<span style="color: #000000; font-weight: bold;">%</span>83<span style="color: #000000; font-weight: bold;">%</span>97<span style="color: #7a0874; font-weight: bold;">&#41;</span>,AAA <span style="color: #7a0874; font-weight: bold;">&#40;</span>音楽グループ<span style="color: #7a0874; font-weight: bold;">&#41;</span> - Wikipedia<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.youtube.com<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">watch</span>?<span style="color: #007800;">v</span>=y3qXINoOURI,AAA（トリプル・エー）<span style="color: #000000; font-weight: bold;">/</span> MUSIC<span style="color: #000000; font-weight: bold;">!!!</span><br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.youtube.com<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">watch</span>?<span style="color: #007800;">v</span>=zrXBmpuikBM,AAA <span style="color: #000000; font-weight: bold;">/</span> 負けない心<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.actagainstaids.com<span style="color: #000000; font-weight: bold;">/</span>,Act Against AIDS - エイズには「知るワクチン」。<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.aaaf.jp<span style="color: #000000; font-weight: bold;">/</span>,アフィリエイトを進化させたアドバンスド アクティブ アフィリエイト<span style="color: #7a0874; font-weight: bold;">&#40;</span>AAA<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
http:<span style="color: #000000; font-weight: bold;">//</span>musicmovie.blog48.fc2.com<span style="color: #000000; font-weight: bold;">/</span>blog-category-<span style="color: #000000;">9</span>.html,AAA<span style="color: #000000; font-weight: bold;">/</span>トリプル・エーのPV動画を無料視聴<span style="color: #000000; font-weight: bold;">/</span>試聴+歌詞 - Music-PV Style -<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.oricon.co.jp<span style="color: #000000; font-weight: bold;">/</span>prof<span style="color: #000000; font-weight: bold;">/</span>artist<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">373048</span><span style="color: #000000; font-weight: bold;">/</span>,AAAの画像、AAAの経歴・プロフィールならオリコン芸能人事典 ...<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.aaaparis.net<span style="color: #000000; font-weight: bold;">/</span>,フランス留学 AAA言語学院<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.pachinko-live.com<span style="color: #000000; font-weight: bold;">/</span>,Pachinko Live<br />
http:<span style="color: #000000; font-weight: bold;">//</span>aaa.avex.jp<span style="color: #000000; font-weight: bold;">/</span>,avex artist academy<br />
http:<span style="color: #000000; font-weight: bold;">//</span>www.daily.co.jp<span style="color: #000000; font-weight: bold;">/</span>newsflash<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">2011</span><span style="color: #000000; font-weight: bold;">/</span>01<span style="color: #000000; font-weight: bold;">/</span>07<span style="color: #000000; font-weight: bold;">/</span>0003722836.shtml,ＡＡＡ・宇野 紅白は最高でした！<br />
$</div></div>
<p>ちゃんと動いてるようです。</p>
<p><a href="http://www.publickey1.jp/blog/11/2011javascript.html">2011年はサーバサイド JavaScript の年</a>らしいですが、ついでに jQuery で爆速スクレイピングコーディングとかいかがでしょう。</p>
<p><img src="http://sakuratan.biz/blog/wp-content/plugins/sakura-icons/icon2.png" width="160" height="160" border="0" style="border:0;float:left" /><br />
んでは<br />
<br clear="left" /></p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/2972/feed</wfw:commentRss>
		<slash:comments>1090</slash:comments>
		</item>
		<item>
		<title>Zen Coding Plugin for jQuery</title>
		<link>http://sakuratan.biz/archives/2394</link>
		<comments>http://sakuratan.biz/archives/2394#comments</comments>
		<pubDate>Thu, 22 Jul 2010 08:25:14 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Zen Coding]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=2394</guid>
		<description><![CDATA[jQuery Zen Coding Plugin を作ってみました。Zen Coding の書式から jQuery オブジェクトを作る感じのやつです。 とりあえずソースとかは http://sakuratan.biz/jquery/zencoding/ に置いてます。オリジナルの Zen Coding と同じで MIT ライセンスです。 使い方 var obj = $.zenCoding('div... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/2394">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>jQuery Zen Coding Plugin を作ってみました。Zen Coding の書式から jQuery オブジェクトを作る感じのやつです。</p>
<p>とりあえずソースとかは <a href="http://sakuratan.biz/jquery/zencoding/">http://sakuratan.biz/jquery/zencoding/</a> に置いてます。オリジナルの Zen Coding と同じで MIT ライセンスです。</p>
<h3>使い方</h3>
<pre>
var obj = $.zenCoding('div#page>div.logo+ul#navigation>li*5>a');
</pre>
<p>で、Zen Coding を展開した jQuery オブジェクトを返します。上の例ですと、</p>
<pre>
&lt;div id="page"&gt;
  &lt;div class="logo"&gt;&lt;/div&gt;
  &lt;ul id="navigation"&gt;
    &lt;li&gt;&lt;a&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
</pre>
<p>の構造を持った jQuery オブジェクトが返ってきます。jQuery オブジェクトってのは $(&#8216;#id&#8217;) とか呼び出した時に返ってくるやつのことす。$.zenCoding の戻り値を他の jQuery オブジェクトにそのまま引っ付けることができるって意味す。</p>
<pre>
var obj = $.zenCoding('div#page>div.logo+ul#navigation>li*5>a');
$('#replace').append(obj);
</pre>
<div style="margin:3em 0">
$.fn も extend してますので、上の例は以下のように書くこともできます。</p>
<pre>
$('#replace').zenCoding('div#page>div.logo+ul#navigation>li*5>a');
</pre>
<p>$.fn.zenCoding は Zen Coding を展開したオブジェクトを append します。中身無い状態で append してもあんまりうれしくないと思いますので、こっちはあんまり使い道無いと思います。
</p></div>
<div style="margin:3em 0">
Zen Coding 展開した結果をテキストで取得したい時は、resultType オプションを $.zenCoding につけて呼び出して下さい。</p>
<pre>
alert($.zenCoding('div#page>div.logo+ul#navigation>li*5>a',
      { resultType: 'text' }));
</pre>
<p>他にもオプションありますが、たぶんあんまり使い道無いと思います。詳しくは <a href="http://sakuratan.biz/jquery/zencoding/">http://sakuratan.biz/jquery/zencoding/</a> をどうぞ。
</div>
<h3>ほかの例</h3>
<p>もう少しややこしい感じのですと、ツイッターのタイムラインに埋め込むツイート部分を Zen Coding で書くとこんな感じになります。面倒くさくなってきたので ul の中身省略してます、サーセンw</p>
<pre style="white-space: normal">
$.zenCoding('li.status&gt;(span.thumb.vcard.author&gt;a.tweet-url&gt;img)+(span.status-body&gt;(span.status-content&gt;(strong+span.entry-content))+span.meta.entry-meta&gt;(a.entry-data+span))+ul.actions-hover+ul.meta-data.clearfix');
</pre>
<p>で、できあがるのはこんな感じの HTML。</p>
<pre>
&lt;li class="status"&gt;
  &lt;span class="thumb vcard author"&gt;
    &lt;a class="tweet-url"&gt;&lt;img src="" alt=""&gt;&lt;/a&gt;
  &lt;/span&gt;
  &lt;span class="status-body"&gt;
    &lt;span class="status-content"&gt;
      &lt;strong&gt;&lt;/strong&gt;
      &lt;span class="entry-content"&gt;&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class="meta entry-meta"&gt;
      &lt;a class="entry-data"&gt;&lt;/a&gt;
      &lt;span&gt;&lt;/span&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;ul class="actions-hover"&gt;&lt;/ul&gt;
  &lt;ul class="meta-data clearfix"&gt;&lt;/ul&gt;
&lt;/li&gt;
</pre>
<p>元の Zen Coding が長ったらしいんでかえってややこしい気がしますwww<br />
という感じですので、もうちょい小分けに使った方がよろしいんでは無いでしょうか。</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/2394/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>arguments.calleeとsetTimeoutを使ってJavaScriptのリトライ処理を簡単に書く方法</title>
		<link>http://sakuratan.biz/archives/2131</link>
		<comments>http://sakuratan.biz/archives/2131#comments</comments>
		<pubDate>Fri, 02 Jul 2010 08:50:40 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=2131</guid>
		<description><![CDATA[jQuery のソースから拾ってきたネタなんすが、arguments.callee と setTimeout を使ったリトライ処理が超便利なのでご紹介。 まず基本形はこんな感じす。 (function() { // なんか処理 if (error) { setTimeout(arguments.callee, 20); } })(); 上のコードは error が真のとき20マイクロ秒後に無名関数... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/2131">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>jQuery のソースから拾ってきたネタなんすが、arguments.callee と setTimeout を使ったリトライ処理が超便利なのでご紹介。</p>
<p style="margin-top:3em">まず基本形はこんな感じす。</p>
<pre>
(function() {
    // なんか処理
    if (error) {
        setTimeout(arguments.callee, 20);
    }
})();
</pre>
<p>上のコードは error が真のとき20マイクロ秒後に無名関数の実行をリトライします。20マイクロ秒だとリトライ間隔が短いような気がするかもしれませんが、リトライ回数は1秒に50回ですので言うほどでもないです。</p>
<p>arguments.callee は関数内でのみ参照可能で、実行中の関数自身への参照を保持します。上の例では arguments.callee は無名関数への参照となります。setTimeout に arguments.callee を渡すその関数を再実行することになります。</p>
<p style="margin-top:3em">実用的なケースで言うと ajax のエラー処理なんかどうでしょう。</p>
<p>ぶっちゃけ ajax のプログラム書いてると、403 とか 404 とかじゃないエラーは一定時間したらリトライさせたいとか多いんじゃないでしょうか。500 とかだいたいバグですし、ネットワークタイムアウトのときはマジでリトライしたい訳ですし。</p>
<p>そんな時こそ arguments.callee ですよ奥さん！！wコードが簡単になること請け合いです。</p>
<pre>
(function() {
    var callee = arguments.callee;
    $.ajax({
        url: 'http://...',
        error: function(xhr, status, e) {
            switch (xhr.status) {
            case 403: case 404:
                throw(xhr.status + ' ' + xhr.statusText);
                break;
            default:
                setTimeout(callee, 60000);    // 60000ms = 1分
                break;
            }
        }
    });
})();
</pre>
<p>error ハンドラの無名関数内で arguments.callee を参照すると error ハンドラそのもの（function(xhr, &#8230;) の方）になりますので、リトライしたい範囲を無名関数で括ってその arguments.callee を（一旦変数に入れてから）呼び出す必要があります。</p>
<p style="margin-top:3em">この方法の便利なところは、エラーによるリトライが後から必要になった場合でも、リトライが必要な箇所を無名関数で括ってしまえば良いだけなので記述が簡単な点です。</p>
<p>似たような処理を setInterval を使って書くこともできますが、リトライを止める時に clearInterval を呼び出さないといけないが結構面倒だったりします。どの程度面倒かは自分で比べてかーさい。</p>
<p style="margin-top:3em">ということで、ある処理が成功するまでリトライするコード（は JavaScript では割と出てくると思います）を書くなら、arguments.callee と setTimeout を組み合わせた方が便利だよっつーお話ですた。</p>
<p><img src="http://sakuratan.biz/blog/wp-content/plugins/sakura-icons/icon2.png" width="160" height="160" border="0" style="border:0;float:left" /><br />
てゆーか arguments.callee ちゃんマジ便利www<br />
<br clear="left" /></p>
<p><a href="http://sakuratan.biz/archives/2171">続く…</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/2131/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>サラッとjQueryプラグインを書けると(･∀･)ｲｲ!!感じ</title>
		<link>http://sakuratan.biz/archives/1597</link>
		<comments>http://sakuratan.biz/archives/1597#comments</comments>
		<pubDate>Fri, 05 Feb 2010 08:53:57 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery プラグイン]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=1597</guid>
		<description><![CDATA[某サイトにて、type=&#8221;text&#8221; の input 要素を、こんな感じで jQuery を使って無効にしていたのですが、 function disable_enter(e) { if (e.which == 13) { return false; } return true; } $(function() { $('.noEnter').keypress(disable_... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/1597">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>某サイトにて、type=&#8221;text&#8221; の input 要素を、こんな感じで jQuery を使って無効にしていたのですが、</p>
<pre>
function disable_enter(e) {
    if (e.which == 13) {
       return false;
    }
    return true;
}

$(function() {
    $('.noEnter').keypress(disable_enter);
});
</pre>
<p>同じ機能を他でも使うことになって、いちいち keypress(disable_enter) 呼び出すのもうっとおしいなと思って、試しに jQuery プラグインにしてみたところ、応用範囲が超スゲー感じだったのでお伝えしたいと思います。</p>
<p style="margin-top:2em">とりま上のをプラグインにするとこんな感じ。</p>
<pre>
(function($) {
    $.fn.extend({
        disableEnter: function() {
            this.keypress(function(e) {
                return (e.which != 13);
            });
        }
    });
})(jQuery);

$(function() {
    $('.noEnter').disableEnter();
});
</pre>
<p>呼び出し側のコードが、超簡単になったのがお分かり頂けるでしょうか？</p>
<p style="margin-top:2em">jQuery プラグインの作り方は、プラグイン関数をメンバに持つオブジェクトを引数に渡すだけです。プラグイン関数内では、this は呼び出しに使用された jQuery オブジェクト（上の例なら $(&#8216;.noEnter&#8217;) が返すオブジェクト）になってますので、元々 jQuery 用に書かれたコードならだいたいそのまま動きます。</p>
<p style="margin-top:2em">元のコードでは「disable_enter を keypress イベントハンドラにセットするとエンター入力でフォームがサブミットされなくなります」という感じで、処理の概要の説明が若干まだるっこしいですが、プラグインにすると「disablEnter() を呼び出すとエンター入力でフォームがサブミットされなくなります」とう感じで、超スッキリします。</p>
<p>ちなみに $.fn.extend ではなく $.extend を使用すると、jQuery そのものの機能を拡張できるのですが、今日はﾒﾝﾄﾞｲので説明省略w</p>
<p style="margin-top:2em">jQuery には<a href="http://plugins.jquery.com/">プラグインディレクトリ</a> もありますので（たぶんエンターを無効にするプラグインはここにありそうw）、これ超イケテルプラグインができたらうｐしたら良いと思うのですが、それほど大したものじゃなくても、jQuery の処理をプラグインにしてパッケージングしておくと再利用性がぐーんと広がるような気がします。</p>
<p>ぜひお試しあれw</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/1597/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
