2008-09-12 Fri

「HTML::Template::Pro」が「HTML::Template」より、かなり早くて助かる

なかなか、HTML::Template::Proを試すのに丁度よいタスクが見つからなかったのですが、僕が使ってるchalowが「HTML::Templeate」というPerlモジュールを使っているので、早速「HTML::Template::Pro」と入れ替えてみました。

- Igor Yu. Vlasenko / HTML-Template-Pro-0.71 - search.cpan.org
-- http://search.cpan.org/~viy/HTML-Template-Pro-0.71/

結論から言うと、僕は人生を沢山損してた、と思いました。

続きを読む

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-12-14 Thu

sitemap.xmlをSitemap0.9対応に変更した

このブログではsitemapを発行してGoogleに食わせていますが、
以前たつをさんの、sitemap生成スクリプトをコピーして、
それからずっと同じスクリプトを使っていました。

最近になって、GoogleだけでなくYahoo!にもクロールして欲しいので、
sitemapのフォーマットををバージョン0.84から0.9に変更しました。
とはいえ、ほとんど変更はないです。

sitemap0.9をcl.itemlistから生成するスクリプト


#!/usr/bin/perl
use strict;
my %hash;
while (<>) {
    $hash{$1} = $hash{$2} = $hash{$3} = 1
if (/^<a href=\"(((\d+-\d+)-\d+)-\d+)/);
}
my $xml;
foreach (sort keys %hash) {
    my $p = (length($_) == 7) ? 0.4 : ((length($_) == 10) ? 0.6 :
    "1.0");
    $xml .= << "URL"
   <url>
      <loc>http://path.to.site/$_.html</loc>
      <changefreq>weekly</changefreq>
      <priority>$p</priority>
   </url>

   URL
}
print << "XML"

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <url>
      <loc>http://path.to.toppage.of.site/</loc>
      <changefreq>daily</changefreq>
      <priority>0.8</priority>
   </url>
$xml
</urlset>
XML
    ;


このスクリプトを使えば、コマンドを実行するだけで
chalowで作ったcl.itemlistからsitemap.xmlを生成できます。

% perl ./sitemap0.9 ./cl.itemlist > ./sitemap.xml


できあがったsitemap.xmlをサーバーにアップすれば作業完了。
生成やアップロードはスクリプトを書いて自動化すると良いでしょう。

http://siteexplorer.search.yahoo.com/にアクセスして、
Yahoo!にもsitemap.xmlを登録してみました。どうなるかな。

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-12-13 Wed

ChangeLogの下のほうが削れてた

まー、まったく何時からだか分からないけれど、
2005年4月24日以前のChangeLogが削れていました。

何故削れてしまったのか分かりませんが、
ChangeLogは定期的にバックアップしているので助かりました。
ツイてる!

かなり前にアクセス数が一気に下がったのですが、
もしかすると、そのころからかもしれません。

ChangeLogのバックアップは定期的に!ですね。

気が向いたので昔の自分の記事を読んだのですが、
いろいろ元気があって良いなーと思いました。
ちょっと見習いたいと思います(笑

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-12-07 Thu

chalowにおけるChangeLogのコメントの便利な使い方">chalowにおけるChangeLogのコメントの便利な使い方

chalowは「* p:」というタイトルを書くことで、
そのタイトル以下から、次のタイトル or 次の日付までのエントリが
コメント扱いされます。

すごくあたりまえのことではありますが、このコメント機能をつかうと、
エントリにするには、まだ十分に書けていないことをストックしたり、
エントリには書けないけれど、エントリとセットで書きたいことを
記録しておくことに使えます。

個人的に、エントリのストックは日付の直後につくり、
エントリにかけないことは、エントリの直下に書くようにしています。

chalowにおけるChangeLogのコメントの例


 2006-12-07  SATOU Toshinori  <satou at lr.pi.titech.ac.jp>

 * p:
 エントリのストック

 * ふつうのエントリ [demo]:
 わーわーゆうてます。

 * ふつうのエントリ [demo]:
 わーわーゆうてます。

 * p:
 エントリには書けないこと

 2006-12-06  SATOU Toshinori  <satou at lr.pi.titech.ac.jp>


chalowは人生を記録するという能力が高いと思いますし、
実は、アサマシ能力もかなり高いので技術者の方に超オススメです。

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-11-15 Wed

chalowでh4とh5を使った小見出しを">chalowでh4とh5を使った小見出しを

このエントリーをはてなブックマークに追加 chalowでh4とh5を使った小見出しを">chalowでh4とh5を使った小見出しを "), 'delicious','toolbar=no,width=550,height=550'); return false;">Delicious [chalow]

1ヶ月以上前にシンプルなchalowに切り替えたけれど、
シンプルすぎて技術系のメモがちょっと見づらい。
個人的には小見出しが、はてな記法のように「**」や「***」だと嬉しい。
これは単純に正規表現を数行書くことで実現できる。

ということで、以下メモ。

chalowによるh4とh5を使った小見出しの実現方法


やること : はてな記法ちっくに「**」や「***」で小見出しを生成
1、sub okikaeの適当なところに以下のコードを挿入する

s|^\*{2}\s(.+?)\n|<h4>$1</h4>\n|g;
s|^\*{3}\s(.+?)\n|<h5>$1</h5>\n|g;

そうすると行頭に「** chalowでh4とh5を使った小見出し」と書くと、

chalowでh4とh5を使った小見出し


となり、行頭に「*** chalowでh4とh5を使った小見出し」と書くと、
chalowでh4とh5を使った小見出し

となる。
# もちろんcssで調整していますが。




このエントリで小見出しを使ってみた。
小見出しのタグがh4とh5になっているのも理にかなっていて良い。
今後はhrによる境界線を入れなくて良いかも。

久々にchalowを拡張してみて気がついたことがひとつ。
昔は正規表現が全然わからなかったけど、今はずいぶん分かるようになってた。

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-09-18 Mon

コメントスパムがすごいので対策した

ここ数ヶ月コメントスパムが大量に投稿されていた。
ときどき手動で消していたけれど時間がもったいないので
日本語混じりの投稿以外は受け付けない設定にした。

くっつきBBSのコメントスパム対策は、
bbs.cgiに以下のように一行追加すればとりあえず完了。
半角英数字のみのコメントを投稿するとdieします。

 my $body = $q->param('body');
+if(($body ne '') && ($body !~ m/[\x80-\xff]/)){ die('error') };


もともと読んでくださっている方が少ないので問題ないかと。

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-06-14 Wed

chalowでChangeLogのエントリを書いた時間をRSSフィードに反映するhack">chalowでChangeLogのエントリを書いた時間をRSSフィードに反映するhack

chalowユーザの方以外には通じない話題ですが、
chalowが出力するRSSフィードは、午前1時に書いたエントリでも、
午後18時に書いたエントリでも、
普通は無条件で23:59:59に書かれたことになります。

23:59:59という時間がエントリを書いた時間と一致しないために、
何とかならないか、と思った人もいると思います。

ということでchalow hack。すごく簡単ですが。

はじめに、エントリの記述時刻をChangeLogに書くときのルールや実装方針を
決めました。たつをさんに相談しました。


これなら、普段のChangeLogを書いていている流れで時間が書けそうです。

では、ChangeLogReader.pmとchalowを書き換えます。
+の文字が先頭についている行を新たに書いています。
上手いこと挿入してください。
-の文字が先頭についている行は消すか、コメントアウトしてください。

・ChangeLogReader.pmのstore_itemサブルーチン

 $entp->{curid}++;
+
+###
+# write time for rss feed & item pages
+###
+my $writetime;
+if ($ih =~ s|\[\s*(\d\d:\d\d)\s*\]\s*:\s*$|:|) {
+    $writetime = $1.":59";
+}
+elsif($ih =~ s|\[\s*(\d\d:\d\d:\d\d)\s*\]\s*:\s*$|:|) {
+    $writetime = $1;
+}
+ $entp->{$entp->{curid}}{wt} = $writetime;
+
 # Processing item header


ChangeLogReader.pmを書き換えたので、
ChangeLogに書いたエントリの記述時刻をRSSフィードや、
アイテムページ(パーマリンクページ)に対して反映できます。

RSSフィードへ反映するには、以下のように書き換えます。

chalowのwrite_rss_fileサブルーチン
-my $item_dcdate = # ($dcdate =~ /^$ymd/) ? $dcdate :
-   $ymd."T23:59:59+09:00";
+my $item_dcdate;
+if ($e->{$i}{wt}){
+    $item_dcdate = $ymd."T".$e->{$i}{wt}."+09:00";
+}
+else{
+    $item_dcdate = $ymd."T23:59:59+09:00";
+}


アイテムページに記述時間を反映したい場合は、
write_item_pageサブルーチンを以下のように書き換えて、
アイテムページのテンプレートに「<TMPL_VAR name=write_time>」と
書けば良いでしょう。

他のテンプレートは、make_item_htmlサブルーチンを書き換えて、
アイテムのテンプレートに「<TMPL_VAR name=write_time>」を書けば
記述時間を反映できます。

chalowのwrite_item_pageサブルーチン
 my $ymdi = "$ymd-$i";
+
+my $writetime;
+unless($ent->{$i}{wt}){$writetime = '23:59:59';}
+else{$writetime = $ent->{$i}{wt};}


 $t->param(url => $item_url); # 2001-01-01-1.html
+$t->param(write_time => $writetime); #hh:mm:59 or hh:mm:ss
 my $ostr = $t->output();


chalowのmake_item_htmlサブルーチン
 (my $item_id = $ymd.$i) =~ s/-//g; # Ex. "200309241"
+
+my $writetime;
+unless($e->{$i}{wt}){$writetime = '23:59:59'}
+else{$writetime = $e->{$i}{wt};}
+
 ### item の組み上げ


 $t->param(url => $item_url);
+$t->param(write_time => $writetime); #23:25
 my $this_item = $t->output();


以上です。

これで、「chalowの出力するエントリは、エントリの記述時刻と
RSSフィードの時刻がズレている」と言われなくなりますね。
実は1年前から気になっていたのでスッキリしました。

投稿者:としのり  日時:23:24:59 | コメント | トラックバック |

2006-05-26 Fri

chalow用のはてな記法プラグイン">chalow用のはてな記法プラグイン

このエントリーをはてなブックマークに追加 chalow用のはてな記法プラグイン">chalow用のはてな記法プラグイン "), 'delicious','toolbar=no,width=550,height=550'); return false;">Delicious [chalow][Perl]

ChangeLogを書くときのスタイルと、最近好みな表示スタイルが
大きく離れたので、chalowの改行処理に手を入れた。
すると、リストっぽい表示が上手いこといかなくなった。

では、どうするか。今回は「Text::Hatenaを使ってみたい」
と以前から思っていたので、Text::Hatenaを使った
chalow用のプラグインを探してみた。
でも、ちょっと検索したところ見つからない。
Text::Hatenaを使う必要性に迫られるchalowユーザが
いないということですかね。

# usage: {{t_h(はてな記法で記述)}}
use Text::Hatena;
sub t_h{ #はてな記法に変換
    my ($text) = @_;
    my $parser = Text::Hatena->new;
    $parser->parse($text);
    my $parsed_text = $parser->html;
    return $parsed_text;
}


これだけ。箇条書き以外には積極的に使う予定がないので、
これで十分。

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |

2006-03-22 Wed

cl.itemlistをsaryで検索

たつをさんと、とくひろさんのエントリを読んでいて
私もAjaxな検索をくっつけてみようかなと思って書くことにしました。
私の開発環境は、あいかわらずDebian Sarge Linuxです。

Saryに興味があったのでSaryを使用。
初めに、Saryをソースからインストールしなくても何とかなるかもと思い
apt-get installしました。

# apt-get install sary

スルスルとSaryがインストールされました。
最新版のSaryではないようです。ちょっと心配。でも気にしない。

次にcl.confのhtmlテンプレートに以下のJavascriptとformを挿入。
たつをさんのコードを、ほぼそのまま流用しました。
3文字より少ないクエリの場合はクライアントサイドで
空表示をするように変更しました。それだけ。

<script type="text/javascript">
    var xmlhttp=false;
    /*\@cc_on \@*/
    /*\@if (\@_jscript_version >= 5)
    // JScript gives us Conditional compilation, we can cope with old IE versions.
    // and security blocked creation of the objects.
    try {
	 xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
	 try {
	     xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	 } catch (E) {
	     xmlhttp = false;
	 }
    }
    \@else
	 xmlhttp=false
    \@end \@*/
    if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
	 try {
	     xmlhttp = new XMLHttpRequest();
	 }
	 catch (e) {
	     xmlhttp=false
	 }
    }
</script>

<script type="text/javascript">
    function countatest_popup(id, key) {
	 if (!document.getElementById) return;
	 var element = document.getElementById(id);
	 if (key.length < 3) {element.innerHTML = ""; return;}
	 key = encodeURI(key); // UTF-8?
	 if (!xmlhttp) return;
	 xmlhttp.open("GET", "sarysearch.cgi?"+key, true);
	 xmlhttp.onreadystatechange=function() {
	     if (xmlhttp.readyState==4 && xmlhttp.status == 200) {
		 element.innerHTML = xmlhttp.responseText;
	     }
	 }
	 xmlhttp.send(null)
    }
</script>

<form name="ol_form" method="GET"action="clsearch.cgi" style="margin:0;padding:0">
<input name="key" size="20" onkeyup="countatest_popup('countatest', this.value);" onfocus="countatest_popup('countatest',this.value);" type="text">
<input value="search" type="submit">
<span id="countatest"></span>
</form>


さらにsarysearch.cgiという名前のPerlプログラムを書いて設置。
このcgiが忙しく働くわけです。

#!/usr/bin/perl

#cl.itemlistをsaryでajax検索。perlで。
#3文字以下のクエリには件数だけを返す仕様
#結果表示がモタモタするのが嫌いならsleepを消す。
use strict;
use warnings;

my $sary_path = "/usr/bin/sary";
my $file_name = "./cl.itemlist";
#ミスタイプの修正を考慮(変わりにイライラするかも)
sleep(1);
print "Content-Type: text/html;\n\n";
#見た目はここで指定。別にいいじゃん。
print '<div class="ajax_sary">';
my $key = ( $ENV{'QUERY_STRING'} );
$key =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("H2", $1 )/eg;
#saryでヒット数カウント(要mksary cl.itemlist)
my $count = `$sary_path -i -c  "$key" $file_name`;
print '*クエリの英字は大文字小文字を別として扱います。<br />';
print '○<b style="background-color:#ffff66">' . $key . '</b>';
#utf8文字列をデコード
unless ( utf8::is_utf8($key) ) {
    utf8::decode($key);
}
#4文字以上のクエリにのみプレビューを返す。
if ( ( $count > 0 ) && ( length($key) > 3 ) ) {
    print 'のヒット数 : ' . $count . '箇所<br />';
    print '○最近の記事<br />';
    #saryで検索(要mksary cl.itemlist)
    my @sary_result = `$sary_path  "$key" $file_name`;
    #検索ノイズを大雑把に消す準備
    my $tag_regex_ = q{[^"'<>]*(?:"[^"]*"[^"'<>]*|'[^']*'[^"'<>]*)*(?:>|(?=<)|$(?!\n))}; #'}}}}
    my $comment_tag_regex = '<!(?:--[^-]*-(?:[^-]+-)*?-(?:[^>-]*(?:-[^>-]+)*?)??)*(?:>|$(?!\n)|--.*$)';
    my $regex  = qq{$comment_tag_regex|<$tag_regex_};
    my $space  = '\x20';
    my $zspace = '(?:\xA1\xA1)';
    my $noise  = '(?:' . $space . '|' . $zspace . ')';
    my $limit;
    foreach (@sary_result) {
	 my ( $link, $title, $body ) = split( '\t', $_ );
	 #リンク抽出
	 $link =~ s|.+href="(.+?)".+|$1|;
	 #カテゴリ表示除去
	 $title =~ s|\[.+?\]$||g;
	 #リンク再構築
	 $link = "<a href=\"$link\">$title</a>";
	 print $link. '<br />';
	 #検索ノイズを大雑把に消す
	 $body =~ s|$regex||gi;
	 $body =~ s|$noise||gi;
	 unless ( utf8::is_utf8($body) ) {
	     utf8::decode($body);
	 }
	 my $snip;
	 #本文中に$keyがあった場合
	 while ( $body =~ m|(.{0,20})$key(.{0,20})|g ) {
	     $snip = $snip . '...' . $1 . '<b style="background-color:#ffff66">' . $key . '</b>' . $2;
	 }
	 #本文中に$keyがなかった場合(タイトルにあるとき)
	 unless ($snip) {
	     if ( $body =~ m|^(.{1,40})| ) { $snip = $1; }
	 }
	 if ( utf8::is_utf8($snip) ) {
	     utf8::encode($snip);
	 }
	 print $snip. '...' . '<br /><br />';
	 $limit++;
	 #検索結果のプレビューは3件まで。
	 if ( $limit >= 3 ) {
	     last;
	 }
    }
    print '○これ以上は検索結果からお探し下さい';
}
elsif ( $count > 0 ) {
    #3文字以下のクエリには件数だけ返す
    print 'のヒット数 : ' . $count . '箇所<br />';
}
else {
    print 'はヒットしませんでした。<br />';
}
print '</div>';


検索窓に0〜2文字までのクエリが入力された場合には、
クライアント側で空表示の処理が行なわれて、
3文字クエリには、Saryによってヒットした箇所の数だけを返します。
4文字以上のクエリには、ヒット箇所の数と、プレビューを数件返します。

ショボいとこ多数。
Saryが大文字小文字を区別するようになってて不便。うーん。
Saryを2回実行しているのが無駄。うーん。
タグの除去はcl.itemlistの生成段階で除去すべきか。うーん。
それにしても、このコード汚くないか? うーん。

まぁ、今後、自分が一番頻繁に使いそうです。

投稿者:としのり  日時:23:59:59 | コメント | トラックバック |