昨日、こんなことを考えてた。
- kkobayashi 大体イメージできてきた。後は実装だな about 14 hours ago from tmitter
- kkobayashi たまに気まぐれで感想書く回があったりするけど…それは見切りをこまめにupdateすることで対応するか about 14 hours ago from tmitter
- kkobayashi 1ダイアリーからシリーズもののタイトルと話数を抜き出す 2カレンダーから1にマッチするものをリストする でOKかな ... about 14 hours ago from tmitter
- kkobayashi ダイアリーなら向こう50日のエントリーから、ローカルなら全探索で。しょぼいカレンダーのエントリーは…ローカルにリストするか、手頃なエントリーにアイキャッチャーをつけるか。特にリモートへのこだわりはないが…SPOCの観点からはリモートか。 ... about 14 hours ago from tmitter
- kkobayashi 未感想管理システムを考える。ローカルのテキストとしょぼいカレンダーを連携させる、またはダイアリーを連携させる。 ... about 14 hours ago from tmitter
最近感想たまりまくってて、今何話目で、どの回の感想を書いて、どの回の感想を書いてなくて・・・という管理が全然できてない。それをいちいち調べるのに1時間くらいかかる始末で、今ひとつ効率が悪い。何より、その1時間でアニメ2本見れるよ・・・。
ということで、考えてみました。一番簡単なのは、ダイアリーとしょぼいカレンダーをリンクさせて、感想を書いてない回をピックアップすると。ダイアリーの作品名としょぼいカレンダーの作品名の対応付けが一番悩んだんだけど、それは「視聴リスト」の表にしょぼいカレンダーのリンクを張ることで対応しようかと。これなら視聴リストをタイムリーにアップデートする必要性も出てきて一石二鳥。
で、実装なのだけど。ここは一つWeb2.0的にAPIを使ってみるかと思ってて、最近公開されたばかりのはてなダイアリーAtomPubでも使ってみるか!と思ったのだけど・・・XML::Atomがうまくインストールできない(こんな感じのエラーが出る)ので、やめることにした。Cygwinはこういうとき困る・・・。ま、WSSE認証とかめんどくさいしね!パスワードとか送りたくないしね!*1
ということで、地道に*2Web::Scraperでもってくることにしました。
use strict; use Web::Scraper; use URI; use Encode; use Data::Dumper; use utf8; my $title_list = "http://d.hatena.ne.jp/kkobayashi/archive"; my $program_list = "http://d.hatena.ne.jp/kkobayashi/20080831/p1"; ## main my ($names, $programs) = get_program_list($program_list); my $titles = get_title_list($title_list); my %reviewed = (); foreach my $header (@$titles){ foreach my $name (keys %$programs){ if($header =~ /$name.*?(\d+)/){ # print encode("sjis", $name), " - $1\n"; $reviewed{$name} = $1 if($reviewed{$name} < $1); } } } my $output ="\n"; foreach my $name (@$names){ my $subtitles = get_calender($programs->{$name}); foreach my $number (sort {$a <=> $b} keys %$subtitles){ $output .= sprintf("%s 第%02d話「%s」\n", $name, $number, $subtitles->{$number}) if($number > $reviewed{$name}); } } print encode("sjis", $output); ## subroutine sub get_title_list{ my $uri = URI->new(shift); print "scraping $uri ...\n"; my $scraper = scraper { process 'li.archive-section', 'list[]', 'TEXT'; }; return $scraper->scrape($uri)->{list}; } sub get_program_list{ my $uri = URI->new(shift); print "scraping $uri ...\n"; my $scraper = scraper { process '//div[@class="section"]/table/tr/td[3]', 'names[]', 'TEXT'; process '//div[@class="section"]/table/tr/td[4]/a', 'programs[]', '@href'; }; my $result = $scraper->scrape($uri); my $table = {}; @$table{@{$result->{names}}} = @{$result->{programs}}; # name => URI return ($result->{names}, $table); } sub get_calender{ my $uri = shift; print "scraping $uri ...\n"; my $scraper = scraper { process '//tr[ @class="past" ]/td[4]', 'number[]', 'TEXT'; process '//tr[ @class="past" ]/td[5]/text()', 'title[]', 'TEXT'; }; my $result = $scraper->scrape($uri); my $table = {}; @$table{@{$result->{number}}} = @{$result->{title}}; # number => title return $table; }
実行すると、こんな感じに出力が出てきます。
S・A〜スペシャル・エー〜 第21話「敵う・叶う」 ストライクウィッチーズ 第08話「君を忘れない」 恋姫†無双 第08話「関羽、黄忠の企みを阻まんとするのこと」 セキレイ 第09話「比礼ト風」 ひだまりスケッチ×365 第03話「5月27日 狛モンスター」 ひだまりスケッチ×365 第04話「3月16日?23日 まろやかツナ風味/10月31日 ガガガガ」 ひだまりスケッチ×365 第05話「3月25日 おめちか」 ひだまりスケッチ×365 第06話「7月30日 さえ太/11月11日 ヒロえもん」 ひだまりスケッチ×365 第07話「4月7日 入学式と歓迎会」 ひだまりスケッチ×365 第08話「10月13日 お山の大将」 ひだまりスケッチ×365 第09話「8月5日 ナツヤスメナーイ/12月3日 裏新宿の狼 PART II」 きらりん☆レボリューション 第124話「ひえひえ! ペンギンさんいらっしゃ?い」 鉄腕バーディー DECODE 第09話「The champion of justice」 マクロスF 第19話「トライアングラー」 マクロスF 第20話「ダイアモンド・クレバス」 マクロスF 第21話「蒼のエーテル」 しゅごキャラ! 第45話「がんばれ!誠一郎!」 しゅごキャラ! 第46話「りま降臨!?お笑いの神様!」 しゅごキャラ! 第47話「あたしが歌唄のマネージャー!?」 テレパシー少女 蘭 第10話「蘭と翠と夏休み」 Yes! プリキュア5 第29話「高原でイケメンとテニス!?」 絶対可憐チルドレン 第22話「孟母三遷!皆本、凶弾に散る!?」 隠の王 第13話「眠らない学舎」 隠の王 第14話「夜の底」 隠の王 第15話「別れの朝」 隠の王 第16話「遠来の客」 隠の王 第17話「決壊の時」 隠の王 第18話「呼ぶ声」 隠の王 第19話「死神の横顔」 隠の王 第20話「戸隠へ」 隠の王 第21話「野望」
ふーむ、これは便利。
どうでもいいけど、これ作るのに大体2時間くらい。数億円のシステムを2時間で!みたいな話が少し前に話題になってたけど、俺が2時間で作れるのはせいぜいこんなもんだ。
*1:負け惜しみ
*2:地道に・・・といっても、Web::Scraperが死ぬほど便利なのはコードを見れば分かるかと・・・。なんだこれ便利すぎ