2006-12-14 Thu
sitemap.xmlをSitemap0.9対応に変更した
このブログではsitemapを発行してGoogleに食わせていますが、
以前たつをさんの、sitemap生成スクリプトをコピーして、
それからずっと同じスクリプトを使っていました。
最近になって、GoogleだけでなくYahoo!にもクロールして欲しいので、
sitemapのフォーマットををバージョン0.84から0.9に変更しました。
とはいえ、ほとんど変更はないです。
sitemap0.9をcl.itemlistから生成するスクリプト
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を登録してみました。どうなるかな。
2006-12-13 Wed
ChangeLogの下のほうが削れてた
まー、まったく何時からだか分からないけれど、
2005年4月24日以前のChangeLogが削れていました。
何故削れてしまったのか分かりませんが、
ChangeLogは定期的にバックアップしているので助かりました。
ツイてる!
かなり前にアクセス数が一気に下がったのですが、
もしかすると、そのころからかもしれません。
ChangeLogのバックアップは定期的に!ですね。
気が向いたので昔の自分の記事を読んだのですが、
いろいろ元気があって良いなーと思いました。
ちょっと見習いたいと思います(笑
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は人生を記録するという能力が高いと思いますし、
実は、アサマシ能力もかなり高いので技術者の方に超オススメです。
2006-11-15 Wed
chalowでh4とh5を使った小見出しを">chalowでh4とh5を使った小見出しを
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を拡張してみて気がついたことがひとつ。
昔は正規表現が全然わからなかったけど、今はずいぶん分かるようになってた。
2006-09-18 Mon
コメントスパムがすごいので対策した
ここ数ヶ月コメントスパムが大量に投稿されていた。
ときどき手動で消していたけれど時間がもったいないので
日本語混じりの投稿以外は受け付けない設定にした。
くっつきBBSのコメントスパム対策は、
bbs.cgiに以下のように一行追加すればとりあえず完了。
半角英数字のみのコメントを投稿するとdieします。
my $body = $q->param('body');
+if(($body ne '') && ($body !~ m/[\x80-\xff]/)){ die('error') };
もともと読んでくださっている方が少ないので問題ないかと。
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年前から気になっていたのでスッキリしました。
2006-05-26 Fri
chalow用のはてな記法プラグイン">chalow用のはてな記法プラグイン
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;
}
これだけ。箇条書き以外には積極的に使う予定がないので、
これで十分。
2006-03-22 Wed
cl.itemlistをsaryで検索
たつをさんと、とくひろさんのエントリを読んでいて
私もAjaxな検索をくっつけてみようかなと思って書くことにしました。
私の開発環境は、あいかわらずDebian Sarge Linuxです。
Saryに興味があったのでSaryを使用。
初めに、Saryをソースからインストールしなくても何とかなるかもと思い
apt-get installしました。
スルスルと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の生成段階で除去すべきか。うーん。
それにしても、このコード汚くないか? うーん。
まぁ、今後、自分が一番頻繁に使いそうです。

