印刷用表示へ切り替え 通常表示へ切り替え 更新履歴を表示 更新履歴を隠す
MovableType リンク切れチェックプラグイン開発のために

リンク切れをチェックして表示する Movable Type 用のプラグインを書くことにした。まずは,コマンドラインで起動する Perl スクリプトを作って動作確認を行う。

■ ■ ■

ブログからのリンク先が消滅しているかどうかを,クリックする前に知りたい。HTML のタグで適当なものがないか探したが,見当たらない (nlog(n): リンク切れを示すタグが欲しい)。そこで,クラスでリンク切れ表示を実装することにした。

概要は次の通り。

  1. ブログ記事の中の外部リンクを抽出
  2. 外部リンクを HTTP でアクセスし,ステータスコードを得る
  3. ステータスコードが 400 以上だったら,アンカータグに class="badlink" 属性を追加
  4. CSS でリンク切れ表示

ステータスコードが 400 番台であればクライアントエラーで,よくあるのが「404 Not Found」。500 番台は相手サーバのサーバエラーで,「500 Internal Server Error」などがある (HTTPステータスコード - Wikipedia)。どちらもアクセスして嬉しくないので,ここではバッドリンクと呼ぶ。

Movable Type には,リンク切れチェックプラグインがすでに公開されている (CheckLinks | Plugins for Movable Type | staggernation.com)。しかし,これは記事の最後にリストアップする形式なので,私がやりたいことは実現できない。

さて,Perl プログラミングに詳しくない人間がスクリプトを書くには,何か手本が必要。材料を集めてみる。

これで書いてみることにする。サンプルプログラム hrefsub のコマンドライン引数の処理は上手い。勉強になる。使わないんだが。

HTTP::SimpleLinkChecker で UTF-8 のページにアクセスすると次のような文句を言われる。

Parsing of undecoded UTF-8 will give garbage when decoding entities at linkchecker.pl

そこで,「$ua->parse_head(0);」でヘッダの解釈を行わないようにする (Parsing of undecoded UTF-8 will give garbage : Protocol.pm - mumumu の日記)。

あまり美しくないが,書いたのは次のコード。

#!/usr/bin/perl -w

sub usage { die "Usage: $0 <file>...\n" }
usage unless @ARGV;

# uncheck my site
my $mysite = "http://your.domain";

package LinkChecker;
use vars qw(@ISA);
use HTTP::SimpleLinkChecker;
require HTML::Filter;
@ISA=qw(HTML::Filter);

sub start {
   my($self, $tag, $attr, $attrseq, $orig) = @_;
   my($code);
   if ($tag eq 'a'
       && exists $attr->{href}
       && $attr->{href} =~ m|^http://|
       && $attr->{href} !~ m|^$mysite|) {
     my $ua = HTTP::SimpleLinkChecker::user_agent();
     $ua->parse_head(0);
     $code = HTTP::SimpleLinkChecker::check_link($attr->{href});
     my $tmp = "<$tag";
     for (@$attrseq) {
       $tmp .= qq( $_="$attr->{$_}");
     }
     $tmp .= qq( class="badlink") if $code >= 400;
     $tmp .= ">";
     $self->output($tmp);
     return;
   }
   $self->output($orig);
}

# Now use the class.

package main;
foreach (@ARGV) {
  LinkChecker->new->parse_file($_);
}

クラスを追加するのに,「$attr->add('class' => 'badlink');」みたいに書けると格好いいんだけど。なんだかそのあたりが直接ガリガリ書くようになってしまっている。

このスクリプトでは,リンク切れの場合,問答無用に「class="badlink"」を追加するので,HTML には制約がある。つまり,a タグには class 属性がないことが前提である。もともと何かの class 属性がある場合でも,その後に class 属性を追加してしまうのだ。

動作確認は,コマンドラインから次のように指定すればよい。

# perl linkchecker.pl file.html

後はこれにオマジナイを追加すればプラグインができる。

2007年6月7日追記:
プラグインを公開しました (nlog(n): リンク切れチェックプラグイン 0.3)。

Posted by n at 2007-06-03 23:51 | Edit | Comments (0) | Trackback(0)
Trackbacks

  • 「手違いで複数トラックバックを送ってしまった!」という場合でも気にしないでください (重複分はこちらで勝手に削除させていただきます)
  • タイムアウトエラーは,こちらのサーバの処理能力不足が原因です (詳細は トラックバック送信時のエラー をご覧ください)
  • トラックバックする記事には,この記事へのリンクを含めてください(詳細は 迷惑トラックバック対策 をご覧ください)
Comments
Post a comment
  • 電子メールアドレスは必須ですが,表示されません (気になる場合は「メールアドレスのような」文字列でもOKです)
  • URL を入力した場合はリンクが張られます
  • コメント欄内ではタグは使えません
  • コメント欄内に URL を記入した場合は自動的にリンクに変換されます
  • コメント欄内の改行はそのまま改行となります
  • 「Confirmation Code」に表示されている数字を入力してください (迷惑コメント対策です)


(必須, 表示されます)


(必須, 表示されません)


(任意, リンクされます)


Confirmation Code (必須)


Remember info (R)?