これらの記事の続き。
XMLパージング
ブログデータをXML形式でダウンロードしたので、とりあずはXMLパーサーに食わせてみます。ここで早速に問題発生。
ExpatError: not well-formed (invalid token): line 96327, column 30not well-formed (invalid token): line 96327, column 30
caty:diary>
これは僕の責任でもあるのですが、生の ^H(BS, 0x08)が入っていたり、違法なバイト列が紛れ込んでいたりしました。
変なバイト列は手で修正したのですが、
ExpatError: undefined entity: line 15218, column 28undefined entity: line 15218, column 28
caty:diary>
アレレ。HTMLとは違い、プレーンなXMLで使える実体参照はわずかです。次の実体参照は未定義でした。
- ö (ö)
- ∧ (∧)
- ≡ (≡)
いずれもダイアリーのコメント内に出現していました。これは「はてな」さんのチョンボでしょ。文字番号による参照か生の文字に直す必要があります。これも手作業で修正。
日(day)のエントリーへの分割
はてなダイアリーの日記形式では、一日分のデータが1個のテキストになっています。しかし、エントリーごとに扱いたいので、このテキストをパーズしてエントリーに分解する必要があります。Kuwataさんにパーザー(分割抽出コマンド)を書いてもらいました。
次のような処理方針です。
- 日(day)は1つ以上のエントリーからなるので、日をエントリー群に分割して取り出す。
- エントリーの作成時刻を表す整数(unixエポックからの秒数)をエントリーIDとして使う。
やってみると、エントリーの作成時刻はユニークだろうという仮定は破られました。
CatyException: AlreadyExists: 1262658439
1262658439
caty:diary>
原因を追求する気も起きないので、手で修正。
すべてのエントリーに作成時刻が入っているという仮定も破綻。次のように、時刻の代わりに「p1」とかが入っているエントリーもありました。
<day date="2009-01-09" title=""> <body> *p1*[リンク][その他代数]余代数の表現とか ...(省略)... </body> </day>
さらに、「日(day)は1つ以上のエントリーからなる」わけでもなくて、空っぽの日もありましたね。
<day date="2012-03-20" title=""> <body> </body> </day>
最初のエントリーが出現する前に文章が書いてる日もあって、それも手で細工。
13メガくらいのXMLファイルをテキストエディタでいじり回してやっとエントリーに分割できました。そしたらですね、なんとなんと、エントリー数がちょうど3000個でした。「日常」カテゴリはちょうど1200個。
$ wc -l hateda-m-hiyama-titles.txt
3000 hateda-m-hiyama-titles.txt$ wc -l hateda-m-hiyama-nichijo-titles.txt
1200 hateda-m-hiyama-nichijo-titles.txt$
記念に、すべてのエントリーのタイトルを列挙したテキストファイルを作りました。それと、「日常」カテゴリのタイトルの一覧も。UTF-8テキストです。