スターのついたブコメをふぁぼったー風に表示する「ぶこめすたー」を公開しました

ご挨拶

この度、スターのついたはてなブックマークコメントをふぁぼったー風に一覧表示するサイト「ぶこめすたー」を作成しましたのでご連絡いたします。
一味違ったはてなブックマークの世界をお楽しみ頂ければと思います。

簡単な説明

このサイトでは、はてなブックマークに登録されたブックマークコメントから、はてなスターがつけられたコメントをピックアップし、時系列順に並べて表示して皆様にお届けしております。
トップページ(デフォルト)では「2人以上のユーザがスターをつけたブックマークコメント」が一覧表示されます。
ブックマークコメントに併せて「コメントがつけられたエントリへのリンク」・「スターをつけたユーザ」なども表示されますので、

  • ブックマークコメントから「面白そうだ」と思ったエントリ/ブックマークページに飛ぶ
  • 興味あるコメントをつけているユーザを探してブックマークページに飛び、「お気に入り」に入れる

など、ブックマークコメントを中心としていろいろお楽しみ頂けるのではないかと思います。ブックマークコメントから始まる恋もあるやもしれませんそんなことはありません。
ちなみに、デザイン・操作感はご覧のとおりふぁぼったーをインスパイアしています、id:ono_matopeさんごめんなさい。あまりにもふぁぼったーに慣れ過ぎて違うデザインが全く思いつかなかったのが真相です。

操作
  • アイコン(大)から、そのユーザのページに遷移できます。そのユーザの(スター付与された)ブックマークコメントが一覧できます。


  • エントリタイトル左のファビコンから、そのエントリについたブックマークコメントが一覧できます(スターがついたコメントのみ)。


  • スターをつけたユーザがアイコンで一覧表示されます。たくさんスターをつけたユーザのアイコンはすこしだけ大きく表示されたりします。そのアイコンからそのユーザのページに遷移できます。
クロール範囲は?

2月10日からクロールを開始しています。それ以前のブックマークについては「ぶこめすたー」に反映されません。
現在ではブックマーク3stars以上のエントリ(少し漏れあるかも)に対し、約2日間程ブックマーク状況・スター付与状況をチェックしてサイトに反映させています。
ですのでしばらくするとクロール対象外エントリとなり、以降スターが増えても「ぶこめすたー」には反映されないことになります。
逆に、上記条件に合うブックマークコメントに関しては30分〜1時間程度で最新状況がぶこめすたーに反映されます。
(クロール範囲は今後改善したいところ)
※すべてのブックマークコメントが網羅できているわけではないことにご注意ください。

今後やりたいこと

  • クロール効率の向上・クロール範囲の拡大
  • 携帯対応とか
  • RSSの配信とか

では

はてなブックマークの新しい見方を提案する「ぶこめすたー」(言い過ぎ)、今後とも宜しくお願い申し上げます。

雑談(有用な情報はありません)

  • クローラはPerlで作成、サイトはPHP+mysqlで構築しています。
  • ようやくPerlが手になじんできました。コードが奇麗かどうかはさておきとして自分の作りたいものが作れるようになってきた感じです。作りながら学ぶほうが自分の性に合っているようです。
  • PHP+DBは今回初挑戦だったのですがまだまだ学ぶべきことが多いと感じます。今回フレームワークなど使用せずイチから作成してみたということで、今後はCakePHPなどにも挑戦してみたいところです。
  • ふぁぼったー完全リスペクトインスパイアなのですがレンタルサーバの能力上503もインスパイアしてしまうんじゃないかとビビっております。
  • 多数のアクセスに耐えられるか心配…でも多くの人に見てほしい…
  • というか計算上、レンタルサーバの使用可能容量が1年程度で尽きそうなのですでにサーバ移転を考え始めています。
  • 次のネタはまだ考えていませんがぼちぼちと検討していこうとしています。次はtwitterか、tumblrか、それともはてな…?
  • いろいろあって評判の悪い.inドメインのイメージ向上になるといいですね。
  • 姉妹サイト「Hatena::Bookmark::24H」(はてブ24H)もよろしくお願いいたします。1H毎のホッテントリを紹介しています。
  • 本日、2月14日はバレンタインデーなどとは呼ばず、「ぶこめすたーリリース記念日」と呼ぶことにします(またそれか)

俺がニュースサイトを語るとこうなるという話

個人ニュースサイト界隈で最も「情報元」になっているサイトTop30
http://www.tandi-communications.net/netnews/090131.php

なんかこのサイトの紹介というか感想とかをエントリにするのが一部流行ってたので。

ゴー











カトゆー家断絶
http://www6.ocn.ne.jp/~katoyuu/
見てない
2年前くらいまで『カトゆ「一家」断絶』と思ってた


■かーずSP
http://www.karzusp.net/
見てない


ゴルゴ31
http://www.golgo31.net/
見てない


楽画喜堂
http://www.rakugakidou.net/
見てない


■everything is gone
http://egone.org/
見てない


アキバBlog秋葉原ブログ
http://blog.livedoor.jp/geek/
見てない


■Hjk/変人窟
http://www.henjinkutsu.net/
見てない


■:::::HK-DMZ PLUS.COM:::::
http://hk.dmz-plus.com/
見てない


BRAINSTORM
http://www5b.biglobe.ne.jp/~nnaro/brainstorm.html
見てない


RinRin王国
http://www.pluto.dti.ne.jp/~rinou/
見てない


■Tentative Name.
http://mew5.com/
見てない


■MOON PHASE
http://www.moonphase.cc/
見てない


■痕跡症候群
http://retro85.blog33.fc2.com/
夜12時になったら見る


■まなめはうす
http://homepage1.nifty.com/maname/
見て、自分のLDRに登録されていないブログを片っ端から入れたりする。まなくんはいつ動くんですか。


■ねたミシュラン
http://netamichelin.blog68.fc2.com/
perlスクリプトで見る(謎)
むしろ日記(ねたミシュランを作ってた人のネタ帳)の方を見てる


■白い戯言
http://d.hatena.ne.jp/whiteball22/
寝坊報告エントリを見る


■さざなみ壊変
http://sazanami.net/
見てない


ぁゃιぃ(*゚ー゚)NEWS
http://semimaru.s47.xrea.com/
見てない


痛いニュース(ノ∀`)
http://blog.livedoor.jp/dqnplus/
見ない


■MOON CHRONICLE
http://miruto.org/
見てない


■好き好き大好きっ
http://www.ne.jp/asahi/yu-show/sukisuki/
見てない


朝目新聞-asame.com
http://www.ne.jp/asahi/asame/shinbun/
見てない


にゅーあきばどっとこむ
http://www.new-akiba.com/
見てない


酔拳の王 だんげの方
http://d.hatena.ne.jp/dangerous1192/
LDRに入ってる


アルファルファモザイク
http://alfalfa.livedoor.biz/
ホッテントリから見る。人間臭くなってきてるよね


■読みゲー
http://denchu.ktplan.net/
ふと見たくなる。ブクマに入れると全部「読みゲー 過去ログ」になる


■ugNews.net
http://ugnews.net/
二郎が恋しくなったら見る


情報屋さん
http://jyouhouya3.net/
見てない


■無駄な領域リサイクル
http://www.mudana.net/
見てない


GIGAZINE(ギガジン)
http://gigazine.net/
トップ画像目が痛いんですけど。



3分くらいで書き終わりました


だから俺に訊くなって言ったのに!

Perlでスレッド処理を行うサンプル少し

はじめに

Hatena::Bookmark::24hのHTMLデータを生成する際にはてなブックマークの個別ページRSSを複数件取得するわけですが、取得処理を勢いで作ってしまったためにスレッド化されていなかったりします。
早い話が1件目のRSS取得→完了→解析→2件目のRSS取得→…のように直列動作させてしまっている状況です。これは効率悪そうです。
並列で複数のRSSが取得できれば処理時間の短縮になりそうですね。ちなみにPerlには並列動作を行う仕組みとしてスレッドが組み込まれているようで、今日はPerlでスレッド処理を行うための処理をメモしておこうかと思います。

注意

実験した環境はWindows XP(SP3)/ActivePerl 5.8.8(Build819)です。それ以外の環境では動作確認していません。

サンプル1:スレッド生成&実行

概要

スレッドを複数個生成・配列(@threads)に格納して各スレッドを一気に実行(join)する

使っているメソッド

threads->new():スレッドを生成する。第1引数はそのスレッド内で動作させる関数を、第2引数以降は第1引数で指定した関数にわたるパラメータとなります。
join:スレッドを実行します。
threads->yield():スレッドの実行権を別のスレッドに渡します。

ソースコード
use strict;
use threads;

my @threads;

print "Create threads\n";
foreach (1 .. 5){
	my $thread = threads->new(\&my_thread, $_);
	push(@threads, $thread);
}

print "Join threads \n";


foreach(@threads){
	my ($return) = $_->join;
	print "$return closed\n";
}

# スレッドの処理
sub my_thread {
	my $i = shift;
	foreach (1 .. 3){
		print "Thread $i($_)\n";
	    threads->yield();
   	    sleep 1;
	}
	return ($i);
}
実行結果
Create threads
Thread 1(1)
Thread 2(1)
Thread 3(1)
Thread 4(1)
Join threads
Thread 5(1)
Thread 3(2)
Thread 1(2)
Thread 2(2)
Thread 5(2)
Thread 4(2)
Thread 1(3)
Thread 2(3)
Thread 3(3)
Thread 5(3)
Thread 4(3)
1 closed
2 closed
3 closed
4 closed
5 closed

各スレッドがかわるがわる動作しているという感じがわかるかと思います。

なぜsleepが必要なのかがいまいちわからない
threads->yield();
sleep 1;

この部分。yieldで次のスレッドに移行すると思ったんだけど。yieldをコメントアウトしてsleepのみでもスレッド移行が行われる。うーむ。

threads->yield()を行わない場合の実行結果

ちなみに、sleepをコメントアウトしたらどうなるか。

Create threads
Thread 1(1)
Thread 1(2)
Thread 1(3)
Thread 2(1)
Thread 2(2)
Thread 2(3)
Thread 3(1)
Thread 3(2)
Thread 3(3)
Thread 4(1)
Thread 4(2)
Thread 4(3)
Join threads
Thread 5(1)
Thread 5(2)
Thread 5(3)
1 closed
2 closed
3 closed
4 closed
5 closed

各スレッド自分の仕事を終わらない限り別のスレッドに実行権を渡してない?のかな?この違いは興味深いですね。
実行のタイミングとか各スレッドがどのように動作しているか等、詳細に確認してみたいところです。

サンプル2:スレッド間で変数を共有する(あまりいい例ではない)

概要

スレッド内で使用する変数は基本的にはローカル(そのスレッドのみで有効)です。各スレッドで共有したい変数にはsharedをつけます。

ソースコード
use strict;
use threads;
use threads::shared; 

my $data : shared;
my @threads;

print "Create threads\n";
foreach (1 .. 5){
	my $thread = threads->new(\&my_thread, $_);
	push(@threads, $thread);
}

print "Join threads \n";

foreach(@threads){
	my ($return) = $_->join;
	print "$return closed\n";
}

# スレッドの処理
sub my_thread {
	my $i = shift;
	foreach(1 .. 20){
		$data++;
		print "Thread $i b($data)\n";
	    sleep 1; # ↑と↓で$dataの出力が変わることがあることに注意
	    		 # タイミングによってはこのスレッドの意図しない値になってることがあるかもよ
		print "Thread $i a($data)\n";
	    threads->yield();
	}
	return ($i);
}
実行結果
Create threads
Thread 1 b(1)
Thread 2 b(2)
Thread 3 b(3)
Thread 4 b(4)
Join threads
Thread 5 b(5)
Thread 2 a(5)
Thread 1 a(5)
Thread 2 b(6)
Thread 1 b(7)
Thread 4 a(7)
Thread 3 a(7)
Thread 4 b(8)  * ←ここから
Thread 3 b(9)
Thread 5 a(9)
Thread 5 b(10)
Thread 2 a(10)
Thread 1 a(10)
Thread 2 b(11)
Thread 1 b(12)
Thread 4 a(12) * ←ここまでの間に
Thread 3 a(12)   他のスレッドが共通変数をいじくり倒していることに注意
Thread 4 b(13)
Thread 3 b(14)
Thread 5 a(14)
Thread 5 b(15)
Thread 2 a(15)
Thread 1 a(15)
Thread 2 b(16)

(以下略)

コメントでも書きましたが自スレッドが動作中に他スレッドが値を変更することがあるので注意。

サンプル3:セマフォを利用して他のスレッドが介入しないように制御する

概要

Semaphore(セマフォ)を使用して変数$dataを参照している間は他のスレッドが割り込んでこないようにする例。
セマフォはおはじきのようなものでnew時に個数が決められます(資源数と呼びます)。downメソッドで1減らし、upメソッドで1増やします。
資源数が0になった状態でdownを行った場合、downが行える状態になるまで(つまり誰かがupするまで)待ち続けます(downメソッドから抜け出ない)。
以下のソースコードでは初期資源数を1としたセマフォ($semaphore)を生成し、
$dataをいじる直前にdown、$dataを使用し終わったらupを行うことにより、downからupまでの期間、他スレッドが$dataを変更できない(downで待ち状態に入る)ようにしています。

ソースコード
use strict;
use threads;
use threads::shared; 
use Thread::Semaphore;

my $semaphore = Thread::Semaphore->new(1);

my $data : shared;
my @threads;

print "Create threads\n";
foreach (1 .. 5){
	my $thread = threads->new(\&my_thread, $_ , $semaphore);
	push(@threads, $thread);
}

print "Join threads \n";

foreach(@threads){
	my ($return) = $_->join;
	print "$return closed\n";
}

# スレッドの処理
sub my_thread {
	my $i = shift;
	my $semaphore = shift;
	foreach(1 .. 20){
		$semaphore->down;
		$data++;
		print "Thread $i b($data)\n";
	    sleep 1; 
		print "Thread $i a($data)\n";
		$semaphore->up;
	    threads->yield();
	}
	return ($i);
}
実行結果
Create threads
Thread 1 b(1)
Join threads
Thread 1 a(1)
Thread 2 b(2)
Thread 2 a(2)
Thread 5 b(3)
Thread 5 a(3)
Thread 1 b(4)
Thread 1 a(4)
Thread 2 b(5)
Thread 2 a(5)
Thread 5 b(6)
Thread 5 a(6)
Thread 1 b(7)
Thread 1 a(7)
Thread 2 b(8)
Thread 2 a(8)
Thread 5 b(9)
Thread 5 a(9)
(略)

スレッドが変数を参照している間、他のスレッドの割り込みが発生していないことがわかるかと思います。
サンプル2の例と見比べてみるとよいかと思います。

サンプル4:Thread::Queueによるデータのやり取り

概要

Thread::Queueを使うと、スレッド間であっても安心してデータのやり取りが可能です。
キュー構造ですのでpush(enqueueメソッド)/pop(dequeue)メソッドを使用して格納・取り出しを行います。
キューに要素が無くなった場合、dequeueメソッドはデータ取得待ちになることに注意(エラー終了などしない。つまりdequeueメソッドが完了しない。データが格納されれば脱出します)です。
ですので下記のソースコードではわざとキューにundefを入れてループ脱出用に使っています。
なお、Thread::Queueで格納できるのはスカラー変数のみとのことです。

ソースコード
use strict;
use threads;
use Thread::Queue;

# データを格納します
my $queue = new Thread::Queue;
foreach (1 .. 100){
	$queue->enqueue($_);
}

my @threads;
print "Create threads\n";
foreach (1 .. 5){
	my $thread = threads->new(\&my_thread, $_);
	push(@threads, $thread);
	$queue->enqueue(undef);
}

print "Join threads \n";


foreach(@threads){
	my ($return) = $_->join;
	print "$return closed\n";
}

# スレッドの処理
# 各スレッドはよきタイミングでデータをqueueから抜き出します
sub my_thread {
	my $i = shift;
	while (my $q = $queue->dequeue){
		print "Thread $i($q)\n";
	    threads->yield();
	    sleep 1*$i; # 各スレッドの動作時間がバラバラになるようにする(実験用)
	}
	return ($i);
}
実行結果
Create threads
Thread 1(1)
Thread 2(2)
Thread 3(3)
Thread 4(4)
Join threads
Thread 5(5)
Thread 1(6)
Thread 2(7)
Thread 1(8)
Thread 3(9)
Thread 1(10)
Thread 2(11)
Thread 1(12)
Thread 4(13)
Thread 1(14)
Thread 5(15)
Thread 3(16)
Thread 2(17)
Thread 1(18)
Thread 1(19)
Thread 2(20)
Thread 1(21)
Thread 4(22)
Thread 1(23)
Thread 3(24)
Thread 2(25)
Thread 1(26)
Thread 5(27)

(中略)

Thread 3(91)
Thread 1(92)
Thread 2(93)
Thread 1(94)
Thread 5(95)
Thread 4(96)
Thread 1(97)
Thread 2(98)
Thread 3(99)
Thread 1(100)
1 closed
2 closed
3 closed
4 closed
5 closed

各スレッド正常にqueueに格納されたデータを取得しています。
Thread::Queueを使用した場合、1つのデータを複数のスレッドが取得してしまうようなことはありません("50"のデータをスレッド1とスレッド2が取得してしまうなど)。

おわりに

このあたりを有効に活用すれば並列データ取得が実現できるかもしれないと思い代表的なスレッド処理を調査してみました。
まだほかに便利そうなメソッドやモジュールがあるみたいですが使う機会がなさそうな予感がするので調べてなかったりします。
なお、Windowsにはネットワークの接続上限数があったはずなので100個並列でデータ取得みたいなことはできないはず。

誕生日を祝ってもらうなどした

1976年1月28日生まれ。33歳になった

ハッピバースデーディア俺ー


大きいろうそく3本、小さいろうそく3本。3並びの33歳。


てなわけでid:BABYPEENATSさんにケーキを買ってもらいお祝いしてもらいましたよ!!



ただし

Ustreamでな!!


僕の誕生日祝いのケーキをid:BABYPEENATSさんがもりもり食べるのをモニタごしに見つつ当方神戸屋のバームクーヘンをもしゃもしゃ食べておりました

それでも

こうやってわいわいと祝ってくれるのはリアルですら経験になかったもので、チャット越しながら涙腺緩みっぱなしのUstream配信でございました。非常に充実した誕生日を過ごせましたありがとう(1日過ぎちゃったけど)!

今年は

「めざせgeekDB入り」を勝手な合言葉とし精進していく次第で御座います。みなさま今後とも「遅れてきた76世代」アシタノ並びにその生成物を宜しくお願い申し上げます。

参考:
http://d.hatena.ne.jp/BABYPEENATS/20090129/1233164886

情報提供系twitterアカウント詰め合わせ

まとまってないけど。羅列でゴー
ブックマークコメントにもあったけど調子に乗ってfollowするとタイムラインがニュースだらけになるので気をつけて。tweenとかのタブ機能をうまく使うのが吉。

Music

@now_onair_tfm

http://twitter.com/now_onair_tfm
TOKYO FMがオンエアしてる曲をPost
@jwave

http://twitter.com/jwave
J-WAVEがオンエアしてる曲をPost
@FM802NowOnAir

http://twitter.com/FM802NowOnAir
関西では有名なFMラジオ局「FM802」がオンエアしてる曲をPost。@ashitano作

はてな

@AnonymousDiary

http://twitter.com/AnonymousDiary
はてな匿名ダイアリーの更新情報。@ashitano作
@qhatena

http://twitter.com/qhatena
人力検索はてな。Qが上がれば教えてくれる
@hatebu3

http://twitter.com/hatebu3
3user以上ブクマがついたエントリを紹介。何か最近止まってないですか。
@hatebustar

http://twitter.com/hatebustar
☆がついたはてブコメントを紹介
@hatebu

http://twitter.com/hatebu
50users以上のホットエントリを紹介

サイト更新情報

@natalie_mu

http://twitter.com/natalie_mu
ナタリー
@gigazine

http://twitter.com/gigazine
GIGAZINE
@famitsu

http://twitter.com/famitsu
ファミ通.com
@otakunews

http://twitter.com/otakunews
オタ系サイト複数の更新情報をまとめてPost
@pb_netallica

http://twitter.com/pb_netallica
ネタりか
@VoiceActBlog

http://twitter.com/VoiceActBlog
声優ブログ更新情報
@2u_reader

http://twitter.com/2u_reader
いろんなサイトの更新情報。詳しくはPostみて
@lifehackerjapan

http://twitter.com/lifehackerjapan
lifehacker[日本版]

@buzztter

http://twitter.com/buzztter
twitterで人気のワードを紹介。
@bombtter

http://twitter.com/bombtter
いつも誰かが何かが爆発しています。「XXX爆発しろ!」に反応する。
@favotter503

http://twitter.com/favotter503
ふぁぼったーの稼動状況をPost
@starred

http://twitter.com/starred
☆がついたPostをtwitterでお知らせ
@KazuyoshiMorita

http://twitter.com/KazuyoshiMorita
アイコン変わったら話かけられる。タモリうぜぇ。@ashitano作
@asshuku

http://twitter.com/asshuku
その日のいろいろなニュースを圧縮しちゃったらカオスなPostに
@nicostar

http://twitter.com/nicostar
☆がついたニコニコ動画をお知らせ

Hatena::Bookmark::24Hで使っているPerlモジュールまとめ

ここを作った時の話

http://hatebu24h.ashitano.in
http://hatebu24h.ashitano.in
1時間単位でブックマークを集めたエントリを紹介しているサイトです。

はじめに

http://hatebu24h.ashitano.inを作る際に使用したPerlモジュールをまとめて紹介しておきます。
というか自分が使い方をよく忘れてしまうのでまとめてメモ。
(ソースは一部改変しています)

メールの受信に「Mail::POP3Client」

使い方
use Mail::POP3Client;

my $yaml = YAML::Tiny->read( 'mailsetting.yaml' );
my $pop = new Mail::POP3Client(%{$yaml->[0]});
# 受信したメール分繰り返し
for(my $i=1; $i <= $pop->Count; $i++){
    # header処理
    foreach($pop->Head($i)){
        # 「$_」がヘッダになる。Date:ヘッダをとったりする
    }
    # 本文処理
    foreach($pop->Body($i)){
        # 「$_」が本文になる。リンクを抽出したりする。
    }
    
    # メール消す
    $pop->Delete($i);
}
$pop->Close;
おまけ

http://hatebu24h.ashitano.inでは、「はてなブックマーク お気に入りメール」の受信に使っています。お気に入りメールは自分のGmailアドレスに転送されるようにしています。
Mail::POP3Client()はハッシュを引数にとります。引数中にハッシュをそのまま記述してもよいのですが設定データとしてyamlファイル(ここではmailsetting.yaml)にハッシュの内容を記載&保存しておき、そのファイルをYAML::Tiny->read()で読み込みPOP3Client()にそのまま放り込んでいます。
ちなみに、yamlファイルはこんな感じです

---
USER: xxxxxx
PASSWORD: xxxxxxxx
HOST: pop.gmail.com
DEBUG: 0
USESSL: true

USER:はメールアカウント、PASSWORDはパスワードですね。DEBUG:を1にすればメール受信時、プロンプト上にメールサーバとの詳細なやりとりが表示されるようになります。

設定データの保存・中間データの保存に「YAML::Tiny」

使い方

(書き込み)

use YAML::Tiny;

my $yaml = YAML::Tiny->new;
$yaml->[0]->{$tag}->[$i]->{url}   = $url;
$yaml->[0]->{$tag}->[$i]->{title} = $title;
$yaml->[0]->{$tag}->[$i]->{count} = $count;
$yaml->write( $yamlfilename );

(生成されたYAMLファイルの一部)

---
1231189200:
  -
    comments:
      -
        comment: 'なんていうか、戦隊に、赤黒青ピンクって、やめません? みたいな。 '
        date: 2009-01-06T06:17:49+09:00
        link: http://b.hatena.ne.jp/REV/20090106#bookmark-11543934
        user: REV
      -
        comment: ~
        date: 2009-01-06T06:05:18+09:00
        link: http://b.hatena.ne.jp/kanose/20090106#bookmark-11543934
        user: kanose
    count: 5
    title: 'もうそろそろアニメで突然やってくる女の子とか、幼なじみとか、やめませんか? - 海ノ藻屑'
    url: http://d.hatena.ne.jp/tokigawa/20090105/p1
  -
    comments:
      -
        comment: ~
        date: 2009-01-06T06:15:57+09:00
        link: http://b.hatena.ne.jp/otsune/20090106#bookmark-11543878
        user: otsune
    count: 4
    title: '噂の作られかた: 韓国が海上封鎖されている?'
    url: http://www.cp.cmc.osaka-u.ac.jp/~kikuchi/weblog/index.php?UID=1231161034

(読み出し)

my $yaml = YAML::Tiny->read( $yamlfilename);
foreach $data (@{$yaml->[0]->{$tag}})
{
    $url   = $data->{url};
    $title = $data->{title};
    $count = $data->{count};
}

自分のソースをほぼそのまま書いちゃったので意味がわからないかもしれませんが、配列とハッシュを自由に組み合わせたデータがそのままファイルに保存&読み出しできるといった感じです。
上記の(生成されたYAMLファイルの一部)を見てもらえるとわかりますが、非常に読みやすい形で出力されます。だからYAML大好き。
http://hatebu24h.ashitano.inでは、ブックマークのRSSを解析した中間データの保存やメール設定を別ファイル化するために使用しています。

参考リンク
おまけ

YAML::TinyはTiny.pmというファイル1つで構成されており、他にモジュールを必要としません。スクリプトを実行するフォルダに置いておけば利用できるというフットワークの軽さが魅力です。

Webデータの受信に「LWP::Simple」

使い方
use LWP::Simple;

my $data_from_web = get($url);
if(!defined($data_from_web)){
    # エラー処理
}
# $data_from_webを解析したり

ブックマークのRSSを受信するのに用いています。受信したデータは後述するRSS解析に回すことになります。

RSS解析・RSS生成に「XML::RSS

使い方

(受信したRSSの解析)

use XML::RSS;

my $rss = new XML::RSS;

eval { $rss->parse($data_from_web); };
if($@) {
    # $rss->parse が失敗したときの処理
}

$title = $rss->{'channel'}->{'title'};
foreach my $item ( @{$rss->{'items'}} )
{
    $date     = $item->{'dc'}->{'date'};
    $user     = $item->{'title'};
    $comment  = $item->{'description'};
    $link     = $item->{'link'};
}

perseした後は、配列・ハッシュとして各要素にアクセスしていくことができて便利です。

(配信用RSSデータの生成)

use XML::RSS;
my $rss = new XML::RSS (version => '1.0');
# タイトルっぽいところの生成
$rss->channel(
   title        => '<![CDATA[' . "Hatena::Bookmark::24H(1時間版)" . ']]>',
   link         => "http://hatebu24h.ashitano.in/",
   description  => '<![CDATA[' . "この1時間でもっともブックマークを集めたエントリは何だ?" . ']]>',
);

# content部を使用したい
$rss->add_module(
    prefix => 'content',
    uri => 'http://purl.org/rss/1.0/modules/content/',
);

# 1件のエントリを生成(RSSデータに追加)
$rss->add_item(
   title       => '<![CDATA[' . $title . ']]>',
   link        => $link,
   description => '<![CDATA[' . $contents . ']]>',
   content => {
        encoded => '<![CDATA[' . $contents . ']]>',
   },
   dc => {
     subject  => "",
     creator  => "ashitano",
     date => $datetime,
   },
   mode  => 'insert'
 );
# $rss->as_stringをファイル化してUPLOAD

それぞれの要素にデータを格納して、as_stringでRSSのデータ文字列を取得、アップロードすればOK。

ファイルのアップロードに「Net::FTP

使い方
$ftp = Net::FTP->new($ftpserveradr, Debug => 1);
$ftp->login($ftpaccount,$ftppassword);
$ftp->put($filename);
$ftp->quit;

生成したHTMLファイルやRSSファイルをアップロードするのに用いています。

おまけ

cwd(フォルダ移動)とかdelete(ファイル削除)とかget(ファイル取得とか)もあります。FFFTP(Windowsかよ)みたいなFTPソフトでできることはほとんどできます。
Debugパラメータを1にすることでMail::POP3Clientのように、サーバとのやり取りをアウトプットすることができます。

そんなわけで

RSSを受信して解析→HTMLに加工→それをアップロードみたいなサイトであればこれらモジュールの組み合わせでなんとかなるもんです、という話でした。

次作について

DB・PHPにチャレンジして新サイトを作成中なのですが頓挫し始めています。自宅のクローラで取得したデータをレンタルサーバのDBに叩き込むとかおかしげなことをしています。そろそろ自宅サーバを導入する頃合かもしれませんがGが足りなくてたびびとのふくくらいしか買えない状況です。

はてなブックマーク聖地へ向けてエントリ四十八箇所巡り

はじめに

はてなブックマーク個別ページのURLの末尾はブックマークされたページのURLとなっているのですが、このURL、エントリIDに置き換えることができます。
たとえば「はてなブックマークトップページ」のブックマークページ(ややこしい) http://b.hatena.ne.jp/entry/http://b.hatena.ne.jp/ の後半「http://b.hatena.ne.jp/」部分は「93」に置き換えられ、「http://b.hatena.ne.jp/entry/93」と表記することもできるということです(もちろん同じページに飛びます)。
このエントリIDはブックマークされたエントリに(はてな内部で)付けられている番号であり、当然ながら数値の小さい順につけられていきます。上記の場合だと「 http://b.hatena.ne.jp/ はブックマークされた93個目のエントリ(サイト)である」ということができます。ちなみに直近のブックマークは1100万番台のIDがついています。

では

ブックマークがついた1番はじめのエントリ(サイト)はなんだろう?

ということで

突然ですが48番からカウントダウンして「初めてブックマークされたエントリ」まで遡って羅列していこうと思います。
まさしく「聖地巡礼の旅」と言えますね。言 え ま す よ ね !!
ということでそれっぽく「札所」とか書いてみました。

ちなみに2005年2月10日にはてなブックマークのベータ版がリリースされていますので、その直後(直前かもしれないが)についたブックマークということになります。記事がないこともしばしば。


では、ゴー

第47番札所 【はてなアンテナ - liddyのアンテナ

最初の訪問者

naoya naoya
訪問時刻:2005-02-10T19:29:06


第44番札所 【Nanoloop

最初の訪問者

bricklife bricklife
訪問時刻:2005-02-10T19:28:45


第43番札所 【みんなでつなげよう!ブログの輪

最初の訪問者

masakano masakano
訪問時刻:2005-02-22T16:06:18


第41番札所 【★リンゴテイ★

最初の訪問者

bricklife bricklife
訪問時刻:2005-02-10T19:27:54


第37番札所 【やさしいタオル

最初の訪問者

oh-kei oh-kei
訪問時刻:2005-02-10T19:24:42


第36番札所 【au ホームページ

最初の訪問者

kiyohero kiyohero
訪問時刻:2005-02-11T02:15:14


第35番札所 【PLUG

最初の訪問者

subtr subtr
訪問時刻:2006-02-15T01:00:39


第34番札所 【馬油と梅雲丹の研究

最初の訪問者

iamshin iamshin
訪問時刻:2008-02-24T16:36:26


第33番札所 【Supleks Dot Com | ブックマーク掲示板

最初の訪問者

iamshin iamshin
訪問時刻:2008-02-24T16:36:26


第32番札所 【はてなブックマーク - 朝日新聞

最初の訪問者

iamshin iamshin
訪問時刻:2008-02-24T16:36:26


第30番札所 【スクールランブルスレ@2ch、分校。

最初の訪問者

sidetail sidetail
訪問時刻:2005-02-10T19:20:02


第29番札所 【No Title

最初の訪問者

folksonomy folksonomy
訪問時刻:2006-02-02T19:02:26


第28番札所 【チープカ

最初の訪問者

iron-scrap iron-scrap
訪問時刻:2005-02-11T19:27:35


第27番札所 【GAFFLING TOKYO

最初の訪問者

jimi_hxs jimi_hxs
訪問時刻:2005-10-07T14:13:07


第26番札所 【はてなブックマーク - ヘルプ

最初の訪問者

nabeso nabeso
訪問時刻:2005-02-10T19:55:48


第25番札所 【シブヤ経済新聞

最初の訪問者

izumi3 izumi3
訪問時刻:2005-06-07T23:58:06


第24番札所 【デイズド&エキサイト:DAZED&Excite

最初の訪問者

sk8 sk8
訪問時刻:2005-06-27T12:49:22


第22番札所 【Yahoo!ニュース - 高齢化社会

最初の訪問者

tanakayoshikazu tanakayoshikazu
訪問時刻:2005-02-10T19:01:18


第20番札所 【NDO::Weblog

最初の訪問者

mathatelle mathatelle
訪問時刻:2005-02-10T21:30:28


第19番札所 【SCAPE

最初の訪問者

folksonomy folksonomy
訪問時刻:2006-02-02T18:49:12


第18番札所 【Yahoo! JAPAN

最初の訪問者

tanakayoshikazu tanakayoshikazu
訪問時刻:2005-02-10T18:59:00


第5番札所 【Wright This Way: iPod Shuffle RAID

最初の訪問者

naoya naoya
訪問時刻:2005-02-10T18:29:36


第2番札所 【はてなダイアリー日記 - 編集画面お試し環境の更新、本日分について

最初の訪問者

onishi onishi
訪問時刻:2005-02-10T18:24:06










みなさまお疲れ様でした。
ついにいちばん初めにブックマークされたエントリにたどり着きました。それは…!











聖地には

既にいくつかブックマークがついていました。http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/hatenadiary/20050208/1107829663 こちらから飛んで聖地巡礼を果たしたブックマーカー達を見てみるのもよいかと思います。

結論

このように札所を訪ねて云々するのは「四国八十八箇所」です。「四十八」は体位の種類の数でした。なんかおかしいなと思ったけど時既に遅し。