nDiki : プラグイン

2004年5月21日 (金)

AWStats 6.0

www.naney.orgアクセスログをローカルにもってきて統計解析をするのに、今回は analog ではなく AWStats を使うことに。

以前 www.naney.org に入れてみた時より、随分使いやすくなった感じ。

セットアップ

Debian パッケージを入れた後、awstats.naney.org というバーチャルドメインをローカルのApacheに用意(/var/www/awstats.naney.org)。

 Alias /icon/ "/usr/share/awstats/icon/"

も設定に追加しておく。

ファイルレイアウト:

 /var/www/awstats.naney.org/
  |
  +-- .htaccess
  |
  +-- awstats.conf  <-- 作成
  |
  +-- awstats.pl    <-- コピーしてきて一部修正
  |
  +-- cache         <-- DNSキャッシュ用 (まだ未使用)
  |
  +-- data          <-- データを保存
  |
  +-- plugins       <-- プラグイン
       |
       +-- wikicker.pm <-- /wiki/(.*).html を $1 で表示するプラグイン(自作)

awstats.pl はパッケージのものをコピー。DecodeEncodedString の中で Jcode.pm を使って文字列を UTF-8 に変換するように修正。

ローカル用なのであまり気にせず DocumentRoot の下にもりっとファイルを置いておく。

awstats.conf はこんな感じ。

 LogFile="/path/to/downloaded-log/access.log"
 LogType=W
 LogFormat=1
 LogSeparator=" "
 DNSLookup=2
 DirData="./data"
 SiteDomain="www.naney.org"
 HostAliases="localhost"
 DNSStaticCacheFile="cache/dnscache.txt"
 DNSLastUpdateCacheFile="cache/dnscachelastupdate.txt"
 URLWithQuery=1
 URLReferrerWithQuery=1
 LevelForWormsDetection=2
 ShowWormsStats=1
 LoadPlugin="wikicker"
 ValidHTTPCodes="200 304 -"

ValidHTTPCodes の '-' というのは、本来不要。自前のSSIで似非 Combined Log を生成する際に '-' を出力する事があるので追加。

日本語もきちんと出るしいい感じ。 指定した月ではなく、指定した日のログを見れるといいのだが設定すればできるようにならないかな。

analog と違ってプラグインが使えるのが良い。 Perlスクリプトだから、その気になれば簡単に awstats.pl 自体を変更する事もできるし。

今回は ShowInfoURL 用プラグインを書いて、/wiki 以下のURLの際は unescape して PageName を表示するようにしてみた。

その他いろいろ遊べそう。

スポンサード リンク
[ 5月21日全て ]

2004年9月9日 (木)

ANTLR

やっぱり手でYAMLのパーサを作成するのが面倒なので(FIRSTとかFOLLOWとか入力バッファ処理とか)、やっぱりジェネレータを使う事を検討。 Java だと ANTLR あたりか。

YAMLだと文脈に応じて、インデント用空白列トークンの長さをかえて認識しなければならないのでそれがうまくできるかどうかがポイント。

まずはインストール(Eclipse 用のプラグインも入れておく)。 ちょっとずつマニュアルも読み始める。

[ 9月9日全て ]

2004年10月16日 (土)

Template Toolkit のテンプレート上で対話的入力

ちょっとしたプログラムパッケージや LaTeX ドキュメントを作成する時に、Makefile やその他ファイルのスケルトンをまとめて生成する算段を検討中。 例えば Perlh2xs のような感じ。

基本的には Template Toolkit ベースでいってみたい。 ttree あたりを使えばだいたいできそうだ。 ここで --define var=value で全て間違えずに指定するのは大変になってくるだろう。 ということでテンプレート変数定義をまとめたテンプレートファイルを作成し、各テンプレート処理をする際にプリプロセスするようにする。

でこのテンプレート変数定義のテンプレートファイルは対話的に作成できるようにしたい。 テンプレートファイルのテンプレートファイルを処理して。

で対話的入力の方法なのだが、探してもそのようなディレクティブもプラグインもみつからない。ありそうなもんだけどなぁ。

しょうがないので、PERL ディレクィブ内で Term::ReadLineを使って入力。 こんな感じ。

 [% TAGS [- -] -%]
 [- PERL -]
 use Term::ReadLine;
 my $term = new Term::ReadLine('template');
 $stash->set('readline' => sub {
   my $prompt = shift || 'input:';
   my $text = $term->readline($prompt);
   if (defined $text) {
     $term->addhistory($text);
   }
   return $text;
 });
 [- END --]
 [% project.name = '[- readline('project name:') -]' -%]
 [% project.author = '[- readline('author:') -]' -%]

tpage でこのテンプレートファイルを処理すると、対話的に値を入力しながらテンプレートファイルを生成できる。 実際は文字列のエスケープなどもうちょっと工夫が必要。

ちなみに Debian GNU/Linux sid の libtemplate-perl は 2.10-1 で、このバージョンの Template Toolkittpage だと EVAL_PERL が有効になっておらずうまく動かない。 手元にコピーして Template オブジェクトの初期化部分に EVAL_PERL => 1 を追加する必要あり (2.14 の tpage は --eval_perl オプションで有効にできる)。

[ 10月16日全て ]

2005年9月13日 (火)

[ WiKicker ] hell mode - HTMLタグ付けブロックの導入

WiKicker では、直接 WikiPageHTMLタグを記述して表示に反映させる機能を提供していない。

HTMLタグ付けを許すのは嫌だ

HTMLタグ付けを許すと

  • 入力ミスによるトラブル
  • 悪意ある入力によるトラブル

が起きやすくなるし、ページのソースの単純さが大きく失われてしまう。 レンダリングしてHTMLにした時に、正しいHTMLを出力されることを保証することが困難になるとともに、HTML以外へのレンダリング/コンバートもかなり難しくなる。

この機能を導入すると、Wiki の良さの半分(あるいはもうちょっと沢山か、もうちょっと少なめ)が失われてしまう。

でも

とはいえ欲しいという声があることも事実。 オープンな WikiForum では全くお勧めできないが、閉じたユーザグループの中ではまぁ必要悪なのかもしれぬ。

また正直ちょっとした表現を追加したい時に、WiKicker 用のプラグインを書くのも面倒だというのは確かにある。

WiKicker では開始・終了マーカによる複数行にまたがるブロックを表すための文法は(閉じ忘れを避けるため)意図的に排除してある。 このため、複数行にわけて書きたいような長いデータを扱うような拡張も導入しにくい。

ちょっと手抜きして「生HTML書けちゃえば」という誘惑はなくはない。

大人の事情

ということでまあ自分に言い訳をしつつ、標準ではオフというかたちで HTMLタグ付けブロックを導入することにした。 スイッチは hell mode とかにしたい (今回は syntax.html というプロパティ名にしたけれど)。

記法は単純に、

 normal wiki syntax text...
 <html>
 html tagged text...
 ...
 </html>
 normal wiki syntax text...

のように行頭が <html> である行から、行頭が </html>である行までをHTMLタグ付けブロックとすることに。 このため、<html>ではじまる段落が書けなくなるという小さな非互換が発生するが、いたしかたない。

サニタイズ

HTMLタグを直接使えるようにするとはいえ、全てを許してしまうのはあまりに危険で非人道的すぎる。 有効なHTMLタグや属性は限定的であるべきだ。

このあたりの処理は面倒だが、幸いにしてCPANにモジュールがある。 今回は HTML::Scrubber を使うことにした。 HTML::Parserを使って parse し、指定したルールに従ってサニタイズしてくれる。

ちょっと使ってみた範囲では日本語(UTF-8UTF8 フラグなし)でも問題ないようだし、文法的に正しくなくてもきちんとサニタイズできているようだ。

ということで、これを採用することに。

どの要素・属性を許すかはまだきちんと決めかねる。 当面は様子をみながら、調整していく予定。 サニタイザは設置者が置き換えられるようにプラガブルにしておかねばならないな。

[ 9月13日全て ]

2006年1月29日 (日)

Last.fm に登録してみる

Last.fm は利用者の音楽プロファイル(好み)をもとに、お薦めの曲をインターネットラジオその他の形式で紹介してくれるというサービスらしい。

様々なミュージックプレーヤー用のプラグインが提供されており、これを利用すること自分が再生したトラックの情報をサーバへ submit していってくれる。 これにより、どんどん自分の好みを設定していけるようになっている。

amaroK にはビルトインでこの機能が実装されている。 設定で Last.fm でのユーザ名とパスワードを入力し、この機能を使うように設定しておくことで再生した曲情報をサーバへ送るようにできる。

面白そうなので早速ユーザ登録し、設定してみた。

で、再生、再生。また再生。

……あれ、Last.fm の自分のユーザページを見ても Recent Tracks は「No recently played tracks to display.」のままだ。

うーん。amaroK の debug 出力をみたり、接続を Proxy 経由にしてそのログで通信状況をチェックしたりしてみたりした範囲では、通信はしているようなのだが。

ちょっと様子見。

[ 1月29日全て ]

2006年2月3日 (金)

amaroK から Last.fm へ送信できるようになった

iTunesプラグイン iScrobbler For Windows 1.1.0 をインストールして、曲を再生してみたところ Last.fm へ曲情報をうまく送信できた。 アカウントの方は特に問題ないらしい。

やはり amaroK 側の問題か。

何度か amaroKsvn 版をコンパイルして試してみるうちに、そういえば configure した際にいくつか optional なライブラリが無くてそれらの機能が外されている旨の表示が出ていたことを思い出した。 apt-get build-dep amarok では全部入らないらしい。

README をみて必要なライブラリを確認。 libmp4v2 あたりが怪しい。ということで libmp4-dev パッケージをインストール。 また前回インストールされていなくて configure に --without-akode していたので aKode 関係のライブラリもあわせていれておく。

で再インストール

で再生してみたら、あっさりうまくいった。

よし。

[ 2月3日全て ]

2006年4月7日 (金)

長年使っていた Window Maker を捨てて KWin

大学で NEXTSTEP に慣れ親しんだこともあって X のウィンドウマネージャ は AfterStepWindow Maker とずっと NEXTSTEP の look and feel を持つものを使ってきた。

しかし昨年秋ぐらいに Konqueror をちょっと使うようになったり、KNewsTicker を使うために KDE パネル (kicker) を表示するようになったりするようになってから、だんだん KDE 臭くなってきた。

KDE パネルを表示していると Window Makerアイコン列とのおさまりが悪いし*1ノート PC の狭い画面を効率的にも使っていない感じになってきた。

ということで、おもいきってウィンドウマネージャも KWin にしてみた。 現時点で使っていた dock app (wmclock、wmbutton、wmtop) は同等の機能をもつ GKrellM プラグインで代替。 GKrellM 用の asclock /wmclock ライクな時計が見つかっていないのがちょっと残念だが、画面すっきり。

KWin への切り換えであるが、てっきり .xinitrc で wmaker を起動するかわりに kwin を起動すれば良いのかと思ったらそれではうまく動かず。かわりに .xinitrc で startkde するようにしたら動くようになった。 そういうものなのか。

*1ちゃんと KDE パネルとは被らないように並ぶのではあるが

[ 4月7日全て ]

2006年4月15日 (土)

sid の CinePaint がプラグイン読み込みでエラー

10枚の「ゴッサム・シティ東京 」を見て HDR イメージに興味を持った。

で早速日中に、手持ちのデジカメで段階露出をした写真を取りためて、家に帰って HDRI 作成に入る。 Linux だと CinePaint あたりが王道か。 CinePaint 0.21 には

  • "Bracketing to HDR" Plugin for CinePaint (Version 0.4.1)

が最初から入っており、段階露出で撮影したデジタル画像から HDR イメージを作成できるのである。

が。

Debian GNU/Linux sid で cinepaint 0.21-1 をインストールして起動してみると、

 /usr/lib/cinepaint/0.20-1/plug-ins/bracketing_to_hdr: symbol lookup error: /usr/lib/libcinepaint.so.0: undefined symbol: gtk_marshal_NONE__NONE
 wire_read: unexpected EOF (plug-in crashed?)

と出てしまうではないが。CinePaint 自体は起動するのだが、プラグインが読みこみ失敗してしまっているようだ。全てのプラグインの読み込みに失敗している様子である。

環境依存かと思いソースパッケージからビルドし直してみてもやっぱり同様。

そんな。

[ 4月15日全て ]

2006年4月16日 (日)

CinePaint で HDR イメージを作れるようになった

昨日の CinePaint のプラグイン読み込みエラーの問題であるが、CinePaint 公式サイトから RPM パッケージを取ってきて alien で deb パッケージに変換しインストールしてみたところうまく動くようになった。

早速使えるようになった Bracketing to HDR プラグインを試す。

[File] -> [New From] -> [Bracketing to HDR] とメニューを選択し段階露出したデジカメ画像を選択、パラメータを調整した後 HDRI xを生成する。

ちなみに昨日外で撮影してきた画像は、露出を変えた各画像がそれぞれ数ドットずれていて使いものにならなかった。 マンフロットの頑丈な奴とはいえやはり卓上三脚FinePix F10 で段階露出するには、メニューをいじって露出補正を変更していかなければならないこともあって、十分固定しておけなかったようだ。

ということであらためて適当に -2EV から +2EV まで 1EV 刻みに段階露出して5枚撮影し CinePaint で処理。

……うーん、いちおうちょっとコントラストがあがった感じの画像になったけれど他の人が作っているようなアーティスティックな感じに仕上らないなぁ。 ここに載せられるような面白そうなものにはならず。

段階露出の幅が足りないのか? FinePix F10 で露出補正だと±2EVまで、マニュアル露出モードはないしどうするか。

広いダイナミックレンジをうまく取れるような景色を探してみればよいのか?

[ 4月16日全て ]

2007年12月29日 (土)

Twitter ベイジアンフィルタプロキシ

Twitter で following が増えてくるにつれて、タイムラインに目を通すのが大変になってきた(という程きちんと見ている訳ではないが)。 さっとタイムラインをなめて面白そうな情報をピックアップしたい時は、「おはよう」とか「風呂入った」とか「トイレ」とかは除外して読みたい(そういう書き込み自体は嫌いじゃないのだが、人生はあまりにも短い)。

Twit や P3:PeraPeraPrv では NG ワード指定ができて、それらを含むステータスは表示しないようにできるのだが、Twitter の書き込みは揺らぎが激しすぎて指定しきれないという弱点がる。

ということでベイジアンフィルタでフィルタリングしてみることにした。

自前で Twitter クライアントを作る気はないので、proxy の形でさっと実装してみた。

 #!/usr/bin/perl

 use strict;
 use warnings;

 use HTTP::Proxy;
 use HTTP::Proxy::BodyFilter::complete;

 my $proxy = HTTP::Proxy->new(port => 8088);
 $proxy->push_filter(response => HTTP::Proxy::BodyFilter::complete->new,
                     mime     => 'application/xml');
 $proxy->push_filter(response => Bsfilter->new,
                     mime     => 'application/xml');
 $proxy->start;

 {

   package Bsfilter;

   use File::Temp qw/tempfile/;
   use XML::XPath;
   use base qw(HTTP::Proxy::BodyFilter);

   sub filter {
     my ($self, $dataref, $message, $protocol, $buffer) = @_;
     return unless defined($$dataref) && $$dataref ne '';
     eval {
       my $xml = XML::XPath->new(xml => $$dataref);
       my @nodes = $xml->findnodes('/statuses/status/text/text()');
       return unless @nodes;
       for my $node (@nodes) {
         my $text = $node->getNodeValue;
         if (is_NG($text)) {
           $node->setNodeValue("[NG] $text");
         }
       }
       $$dataref = qq(<?xml version="1.0" encoding="UTF-8"?>\n);
       $$dataref .= $xml->get_context->toString;
       utf8::encode($$dataref);
     };
     if ($@) {
       warn $@;
     }
   }

   sub will_modify { 1 }

   sub is_NG {
     my ($text) = @_;

     my ($fh, $filename) = tempfile();
     utf8::encode($text);
     print $fh $text;
     close($fh);
     my $result
       = system(
       "bsfilter --homedir ~/.twitter-bsfilter --ignore-header --auto-update $filename"
       );
     unlink($filename);

     return !$result;
   }
 }

HTTP proxy の作成

PerlHTTP proxy を作ろうとして真っ先に思い浮かんだのは POE だけれど、ちょっとヘビーなので今回は HTTP::Proxy をチョイス。 もともとフィルタリング HTTP proxy を作ることを念頭に置いた Perl モジュールなので今回の目的にぴったり。

1つはまった点といえば、filter の呼び出しがレスポンス全てを取得してからではなく一部分ずつの呼び出しになるところ。その仕様に気がつくのにちょっと時間がかかってしまった。 例えば XML 形式のレスポンスをフィルタしようとしても、普通に HTTP::Proxy を使うと XML の一部ずつがフィルタに渡されるため、XML のパースがうまくいかない。

これについては HTTP::Proxy::BodyFilter::complete を使うことで、まとめてフィルタに渡せるようになった。

レスポンスの処理

Twitter のタイムライン取得については P3:PeraPeraPrvXML 形式で取得しているので、そのタイプのレスポンスをフィルタするようにした。

XML::XPath でステータス部分を抜き出して NG 判定し、NG であれば先頭に [NG] を追加する。 これで Twitter クライアント側で [NG] を NG ワード指定すれば、表示されないようにすることができる。

bsfilter による NG 判定

NG 判定は普段メールspam フィルタとして使っている bsfilter を使った。 単純に system 関数で呼び出して結果を取得するだけ。

今回は対象がメールではないので --ignore-header を指定。また自動的に学習するように --auto-update を指定。 それと普段メールのフィルタリングに使っているのとは bsfilterデータベースを別にしたいので、--homedir も指定しておく。

NG と非 NG の学習。

NG ワードを twitter-NG.txt に、非 NG ワードを twitter-clean.txt に書いて以下のコマンドを実行。

 bsfilter --add-clean --ignore-header --homedir ~/.twitter-bsfilter twitter-clean.txt
 bsfilter --add-spam --ignore-header --homedir ~/.twitter-bsfilter twitter-NG.txt
 bsfilter --update --homedir ~/.twitter-bsfilter

自分の環境 (Debian GNU/Linux sid)では、UTF-8 で書いておいて問題なかった。

フィルタリングしてみる

あとは先の proxy を起動し、P3:PeraPeraPrv でプロキシとして localhost:8088 を指定すれば OK。

タイムラインを取得するたびに bsfilter が動いて NG なステータスには [NG] が挿入される。

フィルタリングの精度

これについては、まだまだチューンの必要ありかな。

  • 事前の学習データが少ない。
  • --auto-update していることもあり、最初に NG 判定が多いとそちら側に強化されすぎる。
  • 毎回 bsfilter を呼んでいるため、同じステータスが何度も学習される。

まだ使える精度まで上がってないけれど、教師データを増やせばそれなりにいけるかもしれない。

proxy の枠組ができたので、(@~は抜いてから bsfilter に渡すとか、前後の文脈も含めるとか)いろいろ試して遊べそうではある。 別に bsfilter にこだわらず、正規表現による判定などをしてもよいし。

この辺り P3 は Java で書かれているので、プラグインを書いて拡張できるよう将来になると面白いなと思ってみたり。

[ 12月29日全て ]

About Me

Naney Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。

nDiki1999年1月に始めたコンピュータ日誌を前身とする NaneyWeb 日記(兼パーソナルナレッジベース)です。ちょっとしたノートは nNote にあります。

※内容は個人的見解であり所属組織とは関係ありません。

月別インデックス
Process Time: 0.068785s / load averages: 0.58, 0.57, 0.52
nDiki by WATANABE Yoshimasa (Naney)
Powered by DiKicker