F#でアプリケーションを書こう!今回はいつもと少し趣向を変えて、F#でのアプリケーションプログラミングについて取り上げてみたいと思います。題材として取り上げるのは「2ちゃんねる」の専用ブラウザです。いってもその開発すべてを取り上げるとさすがに退屈になりそうなので、アプリケーションのキモとなる掲示板データのアクセス部分にフォーカスして解説してみます。「2ちゃんねる」にはさまざまな内容をとりあつかう掲示板があり、これらの掲示板はその内容にあわせて便宜上カテゴリー分けされています。掲示板は特定の話題ごとにスレッドという単位で、ユーザーからの書きこみをまとめています。「2ちゃんねる」にアクセスするためのAPIについて特にオフィシャルなドキュメントは存在しないのですが、ネット上の有志の方による資料がいくつか存在します。ここでは参考資料として「専ブラ開発への道」を紹介しておきますが、このブログの記事を理解する上ではこれらのドキュメントを参照する必要は特にありません。カテゴリーごとの掲示板情報の取得さきほど掲示板はその内容にあわせて「便宜上」カテゴリー分けされていると書いたのですが「便宜上」と書いたのには訳があります。いうのもカテゴリーと掲示板の論理的な関係を厳密に取得するAPIというのは特になく、掲示板の一覧を表示するHTML文書の形でしか用意されていないのです。よって、カテゴリーと関連付けて掲示板の一覧情報を入手するには、以下のような形式で記述されているHTML文書をパースすることになります。スレッドリスト掲示板の一覧から掲示板のURLを取得することができます。このURL配下のsubjects.txtというテキストファイルに掲示板のスレッド一覧の情報が収められています。形式は以下のような形式になっており、一行がひとつのスレッドに対応する形になっています。(x)nnnnnnnnnnは10桁の整数であり、スレッドが生成された日時を1970年1月1日00時00分00秒からの経過秒数で表現しています。xは1-1000の整数であり、スレッドに対する書き込み数を表します。書き込み一覧スレッドに対する書き込みの一覧もテキストファイルとしてアクセス可能です。ボードのURLおよびスレッドのIDに基づいて以下のようなURLを合成します。掲示板URL/dat/スレッドID.dat1掲示板URL/dat/スレッドID.datダウンロードしたファイルは以下のような形式になっており、一行がひとつの書き込みに対応する形になっています。JISでエンコードされているので注意してください。ID:ユーザーID<>本文<>スレッド名称ここでも項目の区切りが'<>’になっていることにさえ気を付ければ非常にパースしやすい形式ですが、落とし穴がいくつかあります。HH:mm:ss.ffという形式ですが掲示板/スレッドによっては.ffがありません同様にIDの部分がない掲示板/スレッドもありますスレッド名称は最初の一行にのみ存在します掲示板データの読み込みこれらのカテゴリー、掲示板、スレッドおよび書き込みを以下のようなF#のデータ型として表現することにします。}掲示板にAPIを通じてアクセスするということは、HTTPでダウンロードしたテキストファイルを、これらのデータ構造に変換するということになります。テキストをダウンロードするコードは.NETのライブラリを用いると簡単に実装できるので、ここではテキストファイルを解析して上記のデータ型に変換するところの処理について詳しくみてみましょう。スレッド(書き込みのリスト)の読み込みまずは掲示板の情報そのものともいえるスレッド(書き込みのリスト)の読み込みからみていきましょう。p.Value)先ほどしめした書き込みの形式は正規表現であらわせので、それにマッチした結果に基づいてMoPostの値を返せばよいということなります。Patternとして定義してあります。スレッドリストの読み込みスレッドの一覧もほぼ同様のパターンで実装できます。正規表現の複雑さという観点ではこちらの方が簡単なので特に問題ないでしょう。p.Value)カテゴリーと掲示板の読み込み以上で見たように、スレッドおよび書き込みの情報そのものは正規表現であらわせる形のものでしたので、繰り返し文字列に対してマッチングさせていけばよいだけでした。カテゴリーおよび掲示板の情報そのものも正規表現を使えば問題なく解析できるのですが、厄介なのがカテゴリーと掲示板の階層関係の解析です。おおざっぱにいうとカテゴリーおよび掲示板の一覧を表示するHTMLは以下のような構造になっています。...カテゴリー名および掲示板にマッチする行以外は無視すると、このHTMLファイルはカテゴリー名(CategoryTitle)および掲示板(Board)のリストとしてみなすことができます。このリストを(カテゴリー、掲示板のリスト)というTupleにうまく分割するととができればMoCategoryに変換できそうです。Patternを記述しておきましょう。Patternにマッチした結果を中間表現として一時的にTokenというUnionで表現することにしましょう。すれば件のHTML文書はTokenのリストとして表現できます。]これで、このリストに対してパターンマッチングを適用し、(カテゴリー名、掲示板のリスト)という組を取り出し、それをMoCategoryに変換することができるようになりました。tokens)あと「掲示板のようにみえる行」が最初にあるので、それを読みとばすという処理を追加すると完成です。List.toSeq以上、掲示板のカテゴリー、掲示板、スレッドおよび書き込みのデータをパースする関数が定義できました。以下のようにSystem.Net.WebRequestと組み合わせれば、一応簡単なクライアントモジュールの仕上がりとなります。parseRootMenu以上の関数ほかをモジュールとして定義しているソースはこちらから入手可能です。