html ファイルの文字エンコーディングを調べてみる修行、その 2

Content-Type で明示的に指定されているものだけでなく、Encode::Guess で自動判定したものも表示してみることにした。でもって HTML::Parser の eof メソッドを使って早く終わるようにしてみた。

package CharsetExtractor;
use strict;
use warnings;
use base 'HTML::Parser';

sub get_content_type {
    my ($self, $content) = @_;
    $self->content_type('--undef--');
    $self->parse($content);
    return $self->content_type;
}

sub content_type {
    my $self = shift;
    @_ ? $self->{content_type} = shift : $self->{content_type};
}

sub start {
    my ($self, $tag, $attr) = @_;
    return if $tag ne 'meta';
    my $http_equiv = $attr->{'http-equiv'} || q{};
    return if lc($http_equiv) ne 'content-type';
    $self->content_type($attr->{content});
    $self->eof;
}

package main;
use Path::Class;
use Encode::Guess;

my $parser = CharsetExtractor->new;
my $dir = dir('pages/');
my @candidates = qw{euc-jp shiftjis 7bit-jis utf8};
$dir->recurse( depthfirst => 1, preorder => 0,
               callback => sub {
                   my $file = shift;
                   return if ref($file) ne 'Path::Class::File';
                   my $fh = $file->openr;
                   my $content = do { local $/; <$fh> };
                   my $type = $parser->get_content_type($content);
                   my $enc = guess_encoding($content, @candidates);
                   my $name = ref($enc) ? $enc->name : '--failed--';
                   print "$file\t$type\t$name\n";
               });

追記

丸一日動かしても 13 万件しか処理できてない。340 万件やるには一ヶ月かあ。guess なことはしないで content-type の charset を信じなさい、ってことか。

追記 2009-08-24

途中から Content-type がすべて --undef-- になってしまっている。調べてみると 97755 個目のファイルから。メモリリークしたのかな。