3章 その1 simple-rssでRSS/Atomフィードを読む

3章はクラスタリング
35ページまでかけて複数の英文blogのRSSフィードから単語を切り出し、 http://kiwitobes.com/clusters/blogdata.txt のような単語と出現回数のリストを作っている。このblogdata.txtを使ってしまっても良いのだけど、せっかくだからrubyでやってみる。


本はPythonなので http://www.feedparser.org を使って記事本文データを持ってきて正規表現などでHTMLタグを外したりしているが、
Ruby移植としてまず http://simple-rss.rubyforge.org/ を使って記事本文データやblogタイトルなどを取ってこれるようにする。

sudo gem install simple-rss


p.33のfeedparserと同じ事をやらないとならないので、simple-rssRSSAtomフィードからblogタイトルと記事タイトルと記事本文を取ってこなければならない。
simple-rssAtomRSS両方対応してくれてるのでgood.


まずRSSAtomも、記事本文まで取ってこれるか試すプログラムを書く
simple-rss-test.rb として保存

require 'rubygems'
require 'simple-rss'
require 'open-uri'
require 'cgi'
require 'pp'

puts 'start'

url = 'http://shokai.org/blog/feed'
url = ARGV.shift if ARGV.length > 0

page = open(url)

rss = SimpleRSS.parse( page )

puts 'blog title: ' + rss.channel.title
puts 'blog url: ' + rss.channel.link


rss.items.each{ |item|
  puts 'item_title: ' + item.title
  body = item.content if item.content != nil # atomの時
  body = item.description if item.description != nil # rssの時
  body = CGI.unescapeHTML(item.content_encoded) if item.content_encoded != nil
  puts 'item_body: ' + body
  puts '**********'
}

記事本文がdescriptionだったりcontentだったり、wordpressだとdescriptionに要約が入っててcontent_encodedに本文が入っていたりしたので最後のitems.eachの中身はこうしてみた


一応どれもrss本文が取得できた感じ。


engadget.comのrss

ruby simple-rss-test.rb http://www.engadget.com/rss.xml


gizmode.jpのrss

ruby simple-rss-test.rb http://feeds.gizmodo.jp/rss/gizmodo/index.xml


gizmode.jpのatom

ruby simple-rss-test.rb http://feeds.gizmodo.jp/rss/gizmodo/atom.xml


http://shokai.org/blog/feedatomフィードを読んでみる

ruby simple-rss-test.rb
start
blog title: 橋本商会
blog url: <link>http://shokai.org/blog
item_titlegtalk-sendコマンド
item_body: <p><a href="http://d.hatena.ne.jp/shokai/20081016/1224168536">重い処理が終わったらgoogle talkで通知する - 橋本詳解</a><br />
が便利で、サーバーでの処理が終わったらIM通知するのに使っている。</p>
<p>IMはポップアップして音も鳴るので、Terminalを睨んでなくても良くなる<br />
<a title="google talkで重い処理が終わったら通知 by shokai, on Flickr" href="http://www.flickr.com/photos/shokai/2962103851/"><img src="http://farm4.static.flickr.com/3178/2962103851_b4536ae99b_o.png" alt="google talkで重い処理が終わったら通知" width="318" height="126" /></a></p>
<p>(サーバーで使う物と、自分が普段使うのとでGoogleアカウントが2つ必要)</p>
<p>最近使用頻度が上がってきたので、ちょっとなおした。デフォルト送信先を追加した。設定を、ホームディレクトリに設定ファイルとして置けるようにしたいな</p>
<blockquote><p>#!/usr/bin/ruby</p>
<p>require&nbsp;&#8217;rubygems&#8217;<br />
require&nbsp;&#8217;xmpp4r&#8217;<br />
require&nbsp;&#8217;kconv&#8217;</p>
<p>user&nbsp;=&nbsp;&#8217;your-account@gmail.com&#8217;<br />
pass&nbsp;=&nbsp;&#8217;gmail-password&#8217;</p>
<p>exit(1)&nbsp;if&nbsp;ARGV.length&nbsp;==&nbsp;0<br />
to&nbsp;=&nbsp;&#8217;hashimoto.shokai@gmail.com&#8217;&nbsp;#&nbsp;デフォルトの送信先<br />
to&nbsp;=&nbsp;ARGV.shift&nbsp;if&nbsp;ARGV.length&nbsp;&gt;&nbsp;1<br />
body&nbsp;=&nbsp;ARGV.shift.toutf8</p>
<p>puts&nbsp;&#8217;sending&nbsp;&#8217;&nbsp; &nbsp;body&nbsp; &nbsp;&#8217;&nbsp;to&nbsp;&#8217;&nbsp; &nbsp;to</p>
<p>client&nbsp;=&nbsp;Jabber::Client.new(Jabber::JID.new(user))<br />
client.connect(&#8217;talk.google.com&#8217;,&nbsp;5222)<br />
client.auth(pass)</p>
<p>msg&nbsp;=&nbsp;Jabber::Message.new(to,&nbsp;body)<br />
client.send(msg)</p></blockquote>
<p>これをパスの通ったディレクトリにgtalk-sendという名前にして置いておけば、コマンド一発でGoogleTalkに通知できる</p>
<blockquote><p>gtalk-send hashimoto.shokai@gmail.com &#8220;mag server: レンダリング終了しました&#8221;</p></blockquote>
<p>あるいはデフォルト送信先には引数1つでいける</p>
<blockquote><p>gtalk-send &#8220;mag server: レンダリング終了しました&#8221;</p></blockquote>
<p>コンソールで ; で区切って複数コマンド入力できるので、こんな感じで</p>
<blockquote><p>sudo apt-get update ; gtalk-send &#8220;アップデート終了&#8221;</p></blockquote>
<p>update終わったらIMが来る。</p>
**********
item_titlemoxa - 明るさと振動をシリアル通信で送る
item_body: <p>CdSと振動スイッチを使った。<br />
xtel基盤の<a href="http://www.uc.sfc.keio.ac.jp/xtel/learning/digital-read.html">DigitalRead</a>と<a href="http://www.uc.sfc.keio.ac.jp/xtel/learning/analog-read-write.html">Analog Read</a>のページが大変参考になりました。</p>
<p>このサイズのCdSだと、330ΩをGNDにつないで分圧したら丁度良くなった。<br />
<a href="http://www.flickr.com/photos/shokai/2960178243/" title="DSCF4111 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3137/2960178243_2dac765e1d.jpg" width="500" height="375" alt="DSCF4111" /></a></p>
<p>まずブレッドボードで回路を組んでみた<br />
<a href="http://www.flickr.com/photos/shokai/2960178937/" title="DSCF4114 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3067/2960178937_8b0aabbb5d.jpg" width="500" height="375" alt="DSCF4114" /></a></p>
<p>それからはんだづけ<br />
<a href="http://www.flickr.com/photos/shokai/2961108278/" title="明るさ、振動 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3012/2961108278_b674a54213.jpg" width="375" height="500" alt="明るさ、振動" /></a></p>
<p>プログラム。<br />
連続でシリアル通信するとPCが大変なので、1秒ぐらいのインターバルを取る。<br />
明るさはアナログ値なのでその時間内の平均を取った。<br />
振動も、一度でも振動センサが反応したらshaked:trueになるようにして、serialSendでまとめて送った。</p>
<blockquote><p>serialInit(9600);<br />
pinMode(0,&nbsp;true);&nbsp;//&nbsp;振動センサ</p>
<p>function&nbsp;loop(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;an&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;shaked&nbsp;=&nbsp;false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;loopTime&nbsp;=&nbsp;1000;<br />
&nbsp;&nbsp;&nbsp;&nbsp;for(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;loopTime;&nbsp;i  ){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;an&nbsp; =&nbsp;analogRead(0);&nbsp;//&nbsp;明るさ<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!digitalRead(0))&nbsp;shaked&nbsp;=&nbsp;true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;an&nbsp;=&nbsp;an/loopTime;<br />
&nbsp;&nbsp;&nbsp;&nbsp;serialSend(&quot;light:&quot; an &quot;,shake:&quot; shaked &quot;&yen;r&yen;n&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;sleep(1);<br />
}</p>
<p>function&nbsp;sleep(count){<br />
&nbsp;&nbsp;&nbsp;&nbsp;for(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;count*10;&nbsp;i  ){<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>while(true){<br />
&nbsp;&nbsp;&nbsp;&nbsp;loop();<br />
}</p></blockquote>
<p>PCでシリアル通信受信したところ<br />
<a href="http://www.flickr.com/photos/shokai/2960976604/" title="振動と明るさ by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3050/2960976604_b6a951ebc9.jpg" width="500" height="239" alt="振動と明るさ" /></a></p>
**********
item_titlemoblogプラグインをKtai Entryに変えた
item_body: <p>最初からwordpressに入ってるwp-mailは日本語や写真添付が駄目なので、春頃から<a href="http://shokai.org/blog/archives/1524">wp-shotというのを使ってた</a>んだけど同作者さんが<a href="http://wppluginsj.sourceforge.jp/ktai_entry/">Ktai Entry</a>を出てるのに気づいた。</p>
<p>ふつうcronで定期的にメールサーバにチェックしにいって新着メールがあったら読み出してblog更新するのに、「〜分おきに更新」という設定項目がwordpressの管理画面に出てたのでどうやってるのかと思ったら</p>
<p>blog自体のアクセス毎にメールチェックしにいってたのね。これならcronたしかに要らないなあ</p>
<p>最後にメールチェックした時刻を覚えておいて、例えば10分たってたら再チェックするらしい。</p>
<p>さくらのサーバだとcronでphpを実行させられなくて、 /usr/local/bin/wget -&#8211;spider http://~~~~~.php とかわざわざhttp経由でphpを起動させないと駄目だったので設定が楽になって良いです。</p>
**********
item_titletest
item_body: <div class="photo"><a href='http://shokai.org/blog/wp-content/uploads/2008/10/photo_2.jpg' title='photo_2'><img src="http://shokai.org/blog/wp-content/uploads/2008/10/photo_2-300x225.jpg" width="300" height="225" class="attachment-medium" alt="photo_2.jpg" /></a></div>
</p>
<div class="photo-end"> </div>
**********
item_titlemacbookの液晶がはがれてきた
item_body: <div class="photo"><a href='http://shokai.org/blog/wp-content/uploads/2008/10/photo.jpg' title='photo'><img src="http://shokai.org/blog/wp-content/uploads/2008/10/photo-225x300.jpg" width="225" height="300" class="attachment-medium" alt="photo.jpg" /></a></div>
<p>うつりに特に支障ないけど怖いなあ</p>
<div class="photo-end"> </div>
**********
item_titleArsElectronica
item_body: <p><a href="http://www.flickr.com/photos/shokai/2832305151/" title="DSCF3801 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3024/2832305151_afdcca0e05.jpg" width="375" height="500" alt="DSCF3801" /></a></p>
<p><a href="http://www.flickr.com/photos/shokai/2832995008/" title="DSCF3689 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3172/2832995008_5e78745e5c.jpg" width="500" height="375" alt="DSCF3689" /></a></p>
<p>受賞した作品はみんな面白い<br />
<a href="http://www.flickr.com/photos/shokai/2832289287/" title="DSCF3789 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3262/2832289287_420f4b639e.jpg" width="500" height="375" alt="DSCF3789" /></a></p>
<p><a href="http://www.flickr.com/photos/shokai/2832206419/" title="DSCF3727 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3115/2832206419_274b531a52.jpg" width="500" height="375" alt="DSCF3727" /></a><a href="http://www.flickr.com/photos/shokai/2832183803/" title="DSCF3736 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3251/2832183803_6e13355496.jpg" width="500" height="375" alt="DSCF3736" /></a></p>
<p><a href="http://www.flickr.com/photos/shokai/2832171335/" title="DSCF3703 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3276/2832171335_e34c658bcc.jpg" width="500" height="375" alt="DSCF3703" /></a></p>
<p><a href="http://www.flickr.com/photos/shokai/2825102308/" title="DSCF3574 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3090/2825102308_74f515a03f.jpg" width="500" height="375" alt="DSCF3574" /></a></p>
<p><a href="http://www.flickr.com/photos/shokai/2829761997/" title="DSCF3672 by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3056/2829761997_1bd857d726.jpg" width="375" height="500" alt="DSCF3672" /></a><br />
Blue Bearうまい</p>
**********
item_titleArsElectronicaに展示しに行きます
item_body: <p>KODOUを展示しにオーストリア・リンツで開催されるArsElectronicaに行ってきます<br />
<a href="http://www.aec.at/en/festival2008/program/project.asp?iProjectID=14519">Ars Electronica FESTIVAL: KODOU</a></p>
<p>稲陰研・田中研・奥出研のシニアが7人集まって作った、心音が不思議空間を作るアートです(新作)</p>
<p><a href="http://www.flickr.com/photos/shokai/2816064705/" title="kodou_image_ars by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3258/2816064705_f4ca76950f.jpg" width="500" height="333" alt="kodou_image_ars" /></a></p>
<p>12日ぐらいに帰ってきます</p>
**********
item_titleWPtouchをインストールした
item_body: <p>wordpress用のiPhone/iPodTouch用プラグイン <a href="http://www.bravenewcode.com/wptouch/">WPtouch</a>を入れた</p>
<p><a href="http://www.flickr.com/photos/shokai/2810002119/" title="WPtouch by shokai, on Flickr"><img src="http://farm4.static.flickr.com/3270/2810002119_c7d66f4122_o.jpg" width="320" height="480" alt="WPtouch" /></a></p>
<p>ダウンロードしたアーカイブを解凍して、wp-content/plugins以下に配置して管理画面からプラグインを「使用する」にチェック入れるだけで動いた。</p>
<p>useragentを見て表示をiPhone/iPodTouch用に切り替えてるので、専用URLが生成されるのではないので良い。</p>
**********
item_titleMercurialリポジトリホスティング
item_body: <p>Flashでよく使われるXMLSocketの.NET実装を作っていて、このドメインでもMercurialで管理している<a href="http://shokai.org/projects/xmlsocketnet/hg/">リポジトリを公開している</a>んだけど</p>
<p>最近bitbucketとfreeHgにもコピーしてみた。</p>
<ul>
<li><a href="http://www.bitbucket.org/shokai/xmlsocketnet/overview/">shokai / XMLSocket.NET / overview &#8212; bitbucket.org</a></li>
<li><a href="http://freehg.org/u/shokai/xmlsocket.net/">xmlsocket.net summary - freeHg.org</a></li>
</ul>
<p>これらは<a href="http://github.com/">GitHub</a>のMercurial版で、アカウントを作って自分のリポジトリをコピーして、しかも他の人のプロジェクトが気に入ったらそのままweb上でコピーして改良したりできる。面白い。</p>
<p>bitbucketもfreeHgも日本語のコメントが化けてて困ったけど、今見たらbitbucketは直ってた。これからは積極的にbitbucketにpostするようにしてみるか。</p>
<p>参考:<a href="http://shokai.org/blog/archives/1553">橋本商会&#187; ブログアーカイブ &#187; mercurialを使ってみていて、リポジトリとか公開してみたりした</a></p>
<p>ちなみにXMLSocket.NETは普通のSocketを拡張して作っていて、Flashと接続できるServer、ついでにClient、あとそれらのGUI付きサンプルプログラムができたところ</p>
**********
item_titleubicomp環境での複雑なプログラミング
item_body: <p>現実世界は複雑で主観的なので、正確にモデル化できない。<br />
つまりプログラムの中にモデルとして現実世界の情報を取り込んで、modelの状態に従って処理の手順を分岐させていく方法には無理がある。<br />
そのため、小さくて個別に独立動作するモジュールに分散させて、それぞれのモジュールが環境状態に対応する形で動く様に実装する方が良い。</p>
<h3>■モードのあるプログラム</h3>
<p>複数のモードがあるシステムを実装するとき、一番簡単な方法はglobal変数に状態名を保存しておく事だ。</p>
<p>例えば</p>
<blockquote><p>String state;<br />
state = &#8220;open_mode&#8221;;</p></blockquote>
<p>とか書いておいて、</p>
<blockquote><p>if(state == &#8220;open_mode&#8221;){<br />
// 処理<br />
}<br />
else if(state == &#8220;wait_mode&#8221;){<br />
// 処理<br />
}</p></blockquote>
<p>のようにする。</p>
<p>こういう方法はprocessingやflashで一番最初に作品を作ったりした場合に多くて、まあ楽なのでこれで良い。<br />
processingだとthreadなどが無いのでdraw()ループ内でstateを判別して回すのが楽というのもある。</p>
<p>ただ、この方法には問題がある。</p>
<ul>
<li>stateへのアクセス権限の制限が難しくて、アクセス元が多くなるとバグの元になる</li>
<li>複雑なアプリだとstateの種類自体がものすごく増える<br />
ネットがつながっていて、かつログインしていて、かつ〜〜など。人語にするのも面倒なほどのたくさんの条件から、たくさんの内部状態ができる。</li>
</ul>
<h3>■モードが無いプログラム</h3>
<p>わりと一番簡単なこの手のシステムの実装方法は、threadやtimerがある環境なら<br />
小さいthreadとその連動のためのjob-queueを用意して実装するのが楽な気がする。</p>
<p>ひたすら、<br />
(マイコン内)<br />
1.ボタンの状態を読み続けて、ボタンの状態変化した時に現在時刻とボタンの状態をqueue保存するthread<br />
2.queueを見続けて、何か処理して結果をqueueに保存するthread<br />
3.処理結果を監視し続けて、新しい結果があったらPCにシリアル通信で送り続けるthread<br />
(PC内)<br />
4.シリアルポートを読み続ける<br />
5.なんか処理する</p>
<p>のようにする。この例だと一直線に処理が流れてくるのでまったくqueueを使う必要が無いけど、例えばマイコンで無線の処理も同時にやって、センサ、PC、他のマイコンと3つ又に接続されるように拡張するには、この方法で実装しておいた方が拡張しやすい。queueを監視して処理するthreadをもう一つ足すだけで済むから。</p>
<p>この辺は実装経験の方が専攻していて理論面は最近ちょっと調べた程度なので感覚的なんだけど、<br />
ポイントは、人間の体のように実装する事だと思う。</p>
<h3>■隣を見るだけで全体が動くようにする</h3>
<p>例えば熱い物を触ったときに頭で考えるよりも速く手をひっこめるように、あるいは階段で足を踏み外しても足が勝手にバランスを整えてしまうように、中央に大きな脳があるのではなく各モジュールに小さい脳があり、それが連動する事で人体を成しているようにプログラムを考える。</p>
<p>その手や足の中の脳は体全体や部屋全体を認識しているわけではなくて、皮膚の隣にある熱いコップや、肘ぐらいまでしか認識していない。<br />
このせいでたまにカップ麺を投げて大惨事になったりするけど、最低限<br />
・隣だけ認識する<br />
・環境(外部)からの要因で自動的に動く<br />
ようになっているおかげでなんとか俺は生きている。</p>
<p>グローバル領域にstate変数を置くような実装の場合、自分の中の状態を監視してコードは実行が分岐されるが、<br />
小さなモジュールの中のコードの場合はそうではなく、モジュール自身の中に状態を持たずに環境の状態に応じて処理が分岐される。if条件文で判定される条件式は隣のモジュールへの問いかけになり、帰ってきたメッセージによってコード実行は分岐する<br />
(もちろん実行速度のためにはメッセージの結果はキャッシュしてもいいが)</p>
<p>あと、綺麗にMVCにするには中にmodelを持つわけだけど、XMLのDOMとかと違ってセンサーとか使ってると綺麗にmodelを持つ事自体がすごく難しい事がある。ようはインタフェースからの入力をmodelにするわけだけど、現実世界の現象はそんなに綺麗にmodelになるわけでもないので、むしろ入力に対して適当にレスポンスして、例外的状況をたくさん定義しておく方が良かったりする。</p>
<p>ただし、実験的で何かに特化したプログラミング環境だと、関数をオブジェクトとして扱ったりとか、そういう普通のプログラミング言語として高機能な部分が無くて、こういう実装にはできない事も多い。</p>
**********