超-1の集計をある程度楽にできないかということで始めて見ました。
思い立ったのは講評締め切り当日(2006/6/3)で講評の締め切りに合わせて開始しました。
とりあえずやり方や懸念事項などを明らかにしておくことで、
(もしあれば)次回開催以降の参考等になりましたら、ということで。
これはwww.chokowa.comからHTMLを取り出してきて、perlスクリプトにかけXMLに変換します。
取り回しやすいDBがあればそっちに突っ込んでしまっても良かったのですが
手ごろなDBがなかったのとXML-DBという手もあったのでこれで良かろうと。
HTMLの内容にもよりますが、幸いにも超-1のHTMLは扱いやすかったです。
講評データを舐めて、使用されている名前を引っ張り出せばよいのですが
生憎一人の講評者がいつも同じ名前で投稿してくれるとは限りません。
半角だったり全角だったり、苗字と名前の間にスペースがあったりなかったりします。
なので、講評者DBのXMLは以下のような構造になっています。
<name id="一意な値">hydrogen</name>
<index>94</index>
<filter>(hydrogen|hydrogen)</filter>
これで一人分です。
filterは同一講評者だが名前が若干違うコメントを同定するための正規表現です。
indexというのはCSVなどに変換するときに、何番目の列に名前が現れるか、です。
この要素がなければCSVには変換できませんが自動では無理なので、中間集計のCSVを参考に手で埋めます。
CSVに登場しないがコメントを投稿している(作者さん、TB代行などの非講評)は
indexの要素を負の値としておき、名無し講評は全てindexは0で統一とします。
この講評者の抜き出し作業はXSLTで行います。
ここではxsltprocというXSLTプロセッサ(そのまんま)を使い、データの抜き出し、IDの発行を行います。
同じ(と思われる)人を抜き出して同定のための正規表現を書くのと、indexの割り当ては手で行います。
1と2の結果を合わせ、最終的なXMLを生成します。
2の講評者DBのfilter要素を使って、1の講評者を同定するためです。
具体的には、1の講評の全てに2のIDを振り分け、どの講評が誰のものか解るようにする作業です。
これは再びPerlスクリプトで行いました。
要素から取得した文字列を正規表現としてマッチングさせるのが楽だからです。
やるのは2のXMLからfilterを取り出してマッチングして、マッチしたら s/<name>/<name ref="$id">/ とするだけなので
Perlでも全然楽勝です。
(余談ですが、Perlでは5.8.0以降UTF-8が扱えるようです。
UTF-8にしておくと(文字境界が自明なためか)日本語正規表現が使えて大変ありがたいです。
またPerlでXMLをDOMとして扱うために、XML::DOMモジュールを入手しておきましょう。
perl -CPAN -e shell で install XML::DOM とすればOKですが、root権限が必要になりがちです。)
3で最終的なXMLが手に入ったらあとは楽勝です。
どのような形でも拡張可能です。
で、CSVへの変換ですが、最初XSLTでやろうとして挫折しました。
SQLみたいな完全に集合論の世界なら楽なのですが、ある程度イベントドリブンである程度逐次処理、ある程度集合も書けるという感じで
なかなかCSVにするのがしんどい。
特に悲惨なのが <xsl:value-of select="id(@id)" /> で逆参照が出来ないところ。
これは二重ループにして、articleごとの処理中に、講評者テーブルごとにcommentの集合と付き合わせることが出来ましたが
ここで多重投稿の除去や名無し講評だけ合算とか、その他のワークアラウンドを含めると
物凄くきついことになってしまいます。
で、結局これもPerlで処理したほうがよいという結論に至り。
あとはせいぜい、XMLがでかくなりすぎたので各シーズンに分割するためのXSLとか。
その辺は一通り揃ったらUPします。
思い立ったのは講評締め切り当日(2006/6/3)で講評の締め切りに合わせて開始しました。
とりあえずやり方や懸念事項などを明らかにしておくことで、
(もしあれば)次回開催以降の参考等になりましたら、ということで。
1. 講評データを集める
これはwww.chokowa.comからHTMLを取り出してきて、perlスクリプトにかけXMLに変換します。
取り回しやすいDBがあればそっちに突っ込んでしまっても良かったのですが
手ごろなDBがなかったのとXML-DBという手もあったのでこれで良かろうと。
HTMLの内容にもよりますが、幸いにも超-1のHTMLは扱いやすかったです。
2. 講評データXMLから講評者DBを作る
講評データを舐めて、使用されている名前を引っ張り出せばよいのですが
生憎一人の講評者がいつも同じ名前で投稿してくれるとは限りません。
半角だったり全角だったり、苗字と名前の間にスペースがあったりなかったりします。
なので、講評者DBのXMLは以下のような構造になっています。
<name id="一意な値">hydrogen</name>
<index>94</index>
<filter>(hydrogen|hydrogen)</filter>
これで一人分です。
filterは同一講評者だが名前が若干違うコメントを同定するための正規表現です。
indexというのはCSVなどに変換するときに、何番目の列に名前が現れるか、です。
この要素がなければCSVには変換できませんが自動では無理なので、中間集計のCSVを参考に手で埋めます。
CSVに登場しないがコメントを投稿している(作者さん、TB代行などの非講評)は
indexの要素を負の値としておき、名無し講評は全てindexは0で統一とします。
この講評者の抜き出し作業はXSLTで行います。
ここではxsltprocというXSLTプロセッサ(そのまんま)を使い、データの抜き出し、IDの発行を行います。
同じ(と思われる)人を抜き出して同定のための正規表現を書くのと、indexの割り当ては手で行います。
3. 講評データに講評者IDを振る
1と2の結果を合わせ、最終的なXMLを生成します。
2の講評者DBのfilter要素を使って、1の講評者を同定するためです。
具体的には、1の講評の全てに2のIDを振り分け、どの講評が誰のものか解るようにする作業です。
これは再びPerlスクリプトで行いました。
要素から取得した文字列を正規表現としてマッチングさせるのが楽だからです。
やるのは2のXMLからfilterを取り出してマッチングして、マッチしたら s/<name>/<name ref="$id">/ とするだけなので
Perlでも全然楽勝です。
(余談ですが、Perlでは5.8.0以降UTF-8が扱えるようです。
UTF-8にしておくと(文字境界が自明なためか)日本語正規表現が使えて大変ありがたいです。
またPerlでXMLをDOMとして扱うために、XML::DOMモジュールを入手しておきましょう。
perl -CPAN -e shell で install XML::DOM とすればOKですが、root権限が必要になりがちです。)
4. データの見た目を整える
3で最終的なXMLが手に入ったらあとは楽勝です。
どのような形でも拡張可能です。
で、CSVへの変換ですが、最初XSLTでやろうとして挫折しました。
SQLみたいな完全に集合論の世界なら楽なのですが、ある程度イベントドリブンである程度逐次処理、ある程度集合も書けるという感じで
なかなかCSVにするのがしんどい。
特に悲惨なのが <xsl:value-of select="id(@id)" /> で逆参照が出来ないところ。
これは二重ループにして、articleごとの処理中に、講評者テーブルごとにcommentの集合と付き合わせることが出来ましたが
ここで多重投稿の除去や名無し講評だけ合算とか、その他のワークアラウンドを含めると
物凄くきついことになってしまいます。
で、結局これもPerlで処理したほうがよいという結論に至り。
あとはせいぜい、XMLがでかくなりすぎたので各シーズンに分割するためのXSLとか。
その辺は一通り揃ったらUPします。