Hatena2012-05-12
code:hatena
<body>
*1336824676*作りたいもの:はてなダイアリーのクローラ
** 背景
僕は今まで10年以上Web上での日記をつけ続けているが、いろいろな理由で使うものは変わってきた。今ざっと思い出せるだけでKENTのCGI、PukiWiki、MovableType、Zope、COREBlog、tDiary、Blogger…。はてなダイアリーは今調べてみたら2007年から5年間も使っている。珍しく長く続いている。
しかし、今後5年10年と使い続けるだろうか?いままでなんだかんだで使うものが変わってきたことを考えると、いずれ他のサービスor自前CMSに乗り換える可能性は低くないだろう。で、やめる際にはこのはてなダイアリー上のコンテンツを静的なHTMLにしたりしたくなるだろうな。むしろ、自分の書いたコンテンツが他人のサーバ上にしかないって現状はあんまりよいものじゃないな。まだやめるつもりはないけど今のうちから定期的にクロールして手元に保存しておいたらいいんじゃないかな。
** wgetで?いやいや、それは無理
「Web上のコンテンツをクロールして静的HTMLとして保存する」というとすぐに思いつくのはwget -rを使う方法だろう。だけど、はてなダイアリーの場合それを使いづらい。
僕のはてなダイアリーはd.hatena.ne.jp/nishiohirokazuに置かれている。じゃあその記事に貼られている画像は?おっとはてなフォトライフだからf.hatena.ne.jpだ。ドメインから違う。一時期はてなフォトライフに置くのを面倒に思ってGyazoを使っていたりする。その2つは間違いなく使っているが、他に使っていないか自信がない。じゃあ「外部ドメインに置かれていても画像だけはダウンロードする」ってことでOKか?むむむ、OKかどうか自身が持てない。
** キレイにしたい
さらに言えば、単にはてなダイアリーのHTMLを静的にGETしただけだと色々汚い。
- はてなキーワードへのリンクがいっぱい入っている。取り除きたい。
- シンタックスハイライトは便利に使ってきたけど、これspanでクラスを指定しているだけなので対応するCSSがないと綺麗な色にならない。しかしそのCSSはたぶんはてなの著作物で、勝手に僕のサイトに置くことはできないだろう。
まあでもこれはクロールした後の工程として切り分けるべきか。
** 結局何が必要なのか
- はてなダイアリーをクロールする
- リンクを何でもかんでも辿るのではなく指定したエントリーから指定したエントリーまでの間を「次のエントリー」リンクをたどって取っていく
- 外向きのリンクはどのページからどこへのリンクが貼られていたか、AでかIMGでか、などを記録していく
- 集計結果を見て画像とかをどうするか考える。画像の他に対処しないといけないものがないか考える。
まあキレイにしたいとか色々あるけどそれは保留してスモールスタートにしたほうがいいだろうな。
*1336826780*Alloyガール:ミステリーを作る1
Alloyを使ったミステリー小説の生成に関して「どうやって作ろうか」と考えている過程も割と面白いので記録・公開することにしました。ブログに書かれる「自然言語で書かれたストーリー」とGithubのコミットログの形で進んでいく「コードで書かれたストーリー」が絡み合う「小説の生成過程の小説」です。
** ミステリー部を作る
僕: Alloyさんの頭脳を生かしてミステリー小説を書くことができないだろうか
JS: 面白そう!
Al: それは私に聞いてる?だったら、まず貴方の考える「ミステリー小説」ってのがどんなものか定義して。
僕: えっと、まず人が殺される。
JS: そしてみんな誰が殺したのかわからない。
僕: 「みんなわからない」は間違いじゃない?犯人はわかるわけだし。
Al: そうとは限らないわよ。たとえば「事例1: AさんがBさんを連れて廃墟ビルに入り、自分だけトイレに行くとか言って外に出る。Cさんはそれとは独立に解体工事のために廃墟ビルを爆破する。」これでAとCは結果的に共犯としてBを殺しているけどもAもCもお互いにそのことを知らない。
僕: それは殺人事件じゃなくて事故のような…
Al: あら、じゃあ事故で人が死ぬのとと殺人事件で人が死ぬのの違いを明確にして。
僕: うーむ。
** 「意図」とは何か?
僕: それは「殺害の意図があったかどうか」だと思うけど…
Al: 「意図」とは何?
僕: うーん、事例1の場合、AもCも、事前にBが死ぬとは思ってないわけじゃない?「事例2: Aが事前に廃墟ビルの爆破時刻を知っており、その時間にBをビルの中に入れておけばBが死ぬだろうと予想していた。」これだとAがBを殺したと言える。逆に「事例3: CはAとBがビルに入ったのを目撃したが、ちょうど憎い相手だったので爆破すれば死ぬと予想した上で予定通り爆破を実行した。」これだとCがBを殺したと言える。Aも一緒に殺すつもりだったけどそれは失敗したわけだ。
Al: つまり「ある人Xが、Yが死亡すると予想し、実際にYが死亡する」が殺人事件の定義で、犯人はX?
僕: うん
Al: つまり「事例4: ある人Yがビルの屋上から飛び降りて、それを目撃したXがYが死ぬと予想し、実際に死んだ」はXを犯人とする殺人事件である。
僕: まったまった。えっと、「ある人Xが、*自分の行為によって* Yが死亡すると予想し、実際にYが死亡する」だな。
Al: 「事例3: DはAがビルに入ったのを目撃したが、ちょうど憎い相手だったので、Cに人が入った旨を伝えなかった。結果Cは予定通りビルを爆破し、Aは死んだ」は殺人事件ではない、と。
僕: むむむ。「自分に都合のいい事態が起きるように知っていることをあえて言わない」ってのはミステリーの頻出パターンのような気がするなぁ。「知っていることを言わない」も行為に含めてはどうか。
Al: いいわよ。行為には具体的には「知っていることを言わない」の他に「爆破」と「置き去り」があるのね。
僕: まあ、他にもナイフで刺すとか銃で撃つとか、いろいろね。
** 「謎」とは何か?
Al: で、殺人事件が起きたらそれはミステリー?
僕: いや、条件がだいぶ足りない気がする。
Al: 「事例5: Xさんがみんなの前でYさんを刺して殺しました」は殺人事件だけどミステリーじゃない、と。
僕: そうだねぇ、全然ミステリーじゃないねぇ。
Al: 何が足りないの?
僕: うーん、謎?
Al: じゃあ謎って何か定義して。
僕: えっと…
JS: 「誰が殺したのかわからない」!
僕: そうだ。それだ。
Al: 「事例6: Xさんが殺されました。誰が殺したのかわかりませんでした。終わり。」
僕: いや、それは困る。「犯人は文章の初期に登場する」「最終的には犯人が明らかになる」も必要だ。
** 謎はなぜ解ける?
Al: なぜ犯人が明らかになるの?
僕: え?
Al: 「犯人がわからない」という状態から「犯人がわかる」という状態への遷移は何が引き起こすの?
僕: それは…新しい情報だな。誰かが証言したりとか、物証が見つかったりとか。
Al: 「事例7: Xさんが殺されました。誰が殺したのかわかりませんでした。Yさんが『私が殺しました』と自供しました。謎は全て解けた!」
僕: いや、自供で解決するのは困る…
Al: 「事例8: Xさんが殺されました。誰が殺したのかわかりませんでした。Yさんが監視カメラに映ってました。謎は全て解けた!」
僕: ぐむむ…単独の物証で解決されるのも困るな…
Al: 「事例8: Xさんが殺されました。誰が殺したのかわかりませんでした。犯行時刻のアリバイがないのはAさんとBさん。凶器を入手可能なのはAさんとCさん。犯人はAだ!」
僕: あー。うーん、まだ簡単すぎる気はするけど、だいぶミステリーっぽくなったかなぁ??
Al: N個目の情報で犯人が確定するけど、N-1個目まででは確定しない、ってパターンなら探せるわよ。
** 強い証拠が多すぎると良くない?
僕: じゃあ、「登場人物の紹介」→「殺人事件発覚」→「情報収集」→「探偵役が『謎は全て解けた』宣言」→「謎解き」ってストーリー構成でどうだろう。
Al: どうだろう、って言われても。
僕: そういうストーリーで一筆お願いします。
Al: え、書けって言ってる?ムリムリ、まだ全然情報が足りないじゃない?
僕: 足りない?
Al: まず「犯人が明らかになる」とは何か。
僕: その人以外の犯行が不可能だとわかること。
Al: 「犯行が不可能だとわかる」とは何か。
僕: えーと、その人が犯人だと仮定すると他の情報と矛盾が起きる、ってこと。
Al: で、情報には例えばカメラに写ったなどの物証があるわけね
僕: うん
Al: 「事例9: A, B, Cさんの中に犯人がいます。Aさんにはアリバイがあります。Bさんにもアリバイがあります。犯人はCだ!」これは条件を満たすわね。
僕: ぐむむ…。確かに単独の証拠では犯人が確定しない。
Al: 単独の証拠で犯人が確定することを嫌ったのは、問題が簡単になりすぎるからでしょ?
僕: うん。
Al: だったら、単独の証拠で、ある登場人物が犯人でないと確定するのも問題が簡単になりすぎるんじゃない?
僕: あー、そうか、確かにそうだなぁ。
** 状況設定を考える
僕: じゃあこういうのはどうだろう。いくつかの「場所」があって、その場所の間の移動には1.5単位時間かかる。
Al: ふむ。
僕: つまり、あるタイミングで場所Xにいたなら、単位時間後にX以外の場所にいることはできない。2単位時間後にはどこにいる可能性もある。
Al: 続けて。
僕: そして、各場所は十分に狭く、そこの場所にいたなら他に誰がいたかは確認できる。
Al: Xが時刻t1にP1にいた、って情報からはXが単位時間後t2にP1以外にいない、ってことだけが言えるわけね。充分弱そうね。
僕: さらに、犯人は自分の犯行を隠す目的で嘘をつく可能性がある。
Al: いいねいいね、緩くなってきたね。
僕: しかも犯人が1人であるとは限らない。
Al: おっと。そこまで行くと制約が緩すぎね。「全員共犯で嘘を付いている」っていうトリビアルな解が存在するじゃん。
僕: うーん、でも「犯人は1人です」って宣言するのも不自然だし…。
Al: 「最後の一つの情報で犯人集団が一通りに定まる」って制約を満たすなら「登場人物の証言が次々に自己矛盾していき、最後の証言も自己矛盾して全員犯人」って解があるわね。うまく書けば意外と読者に気づかれないんじゃない?
僕: えー、でももうここでネタバレしちゃったしなぁ。物証かなにかでなんとかならないかな…
Al: なんともならないわね。物証と証言が一致する場合、それは犯人が正直なことを言っただけかもしれないので何の判断材料にもならない。一方、物証と証言が矛盾する場合、証言者が犯人であることがあっさり確定する。
僕: うーむ…
** 逆に正直者を導入したらどうか
Al: 「嘘をつく可能性のある人は最大N人である」と制約を明記するのが嫌だったら、似たような制約を別の表現で入れたらどう?たとえば「村の祭りではM人が神に捧げる踊りを踊る。この役に選ばれた村人は祭りの期間、宗教上の理由により絶対に嘘をついていはいけない」とか。
僕: なるほど。それならありかも。
Al: 誰が踊り子なのかも他の村人から聞くことにすれば村人間の相互作用があっていいんじゃない?
僕: つまり村人は「Xは踊り子だ」「Xは時刻Tに場所Pにいた」の2通りの発言ができる、と。
Al: まずは小さい規模で、容疑者3人、1人が犯人、1人が犯人をかばって嘘をつくかもしれない人、1人が踊り子で正しいことしか言わない、という設定でどれくらいの難易度の謎が生まれるか検証するべきね。
僕: 探偵役を導入して「彼の見聞きしたものは物証同様に正しい」としてもいいかもね。
Al: まあまずはそれも入れずにシンプルなモデルでスタートすべきよ。
僕: そうだよね、夢が広がってついついいろんな物を入れたくなってしまう。探偵役の見聞きした情報から、探偵が正直だとわかっている読者は犯人がわかるのだが、村の他の人にとっては探偵はよそ者で嘘をつく可能性があると考えられていて犯人を逮捕してくれないとか。で、証拠探しが始まる、というのはどうか。
Al: 物事を複雑にするの得意ね。まずは前半がうまく動くことを確認してからにしましょう。
** 次回予告
Github上でmystery.alsをいじりながら色々試して、それから自然言語での続きが書かれる感じ。
</body>