プログラマでありたい

おっさんになっても、プログラマでありつづけたい

HTML::ExtractContentで文字コード絡みで悩む

HTML::ExtractContentを使っているのですが、下記のような警告が出て困りました。

Malformed UTF-8 character (unexpected continuation byte 0x84, with no preceding start byte) in pattern match (m//) at /usr/lib/perl5/site_perl/5.8.8/HTML/ExtractContent/Util.pm line 69.

要は、ちゃんとしたUTF8の文字列を使えよということです。エラーが起きるのは、以下の箇所。

sub match_count {
    my ($str, $exp) = @_;
    my @list = ($str =~ $exp);
    return $#list + 1;
}

そして、問題になる正規表現は、次のようなものです。

punctuations => qr/([。、.,!?]|\.[^A-Za-z0-9]|,[^0-9]|!|\?)/is,

マルチバイトの文字列が、悪さをしているのは間違いなさそうです。呼び元のソースは、次のような物でした。Encodeで一旦utf8に変換後、ExtractContentに流しています。

my $enc = guess_encoding($content);
my $from = $enc->name;
if ($from ne "utf8") {
  from_to($content, $from,"utf8");
}

my $extractor = HTML::ExtractContent->new;
$extractor->extract($content);


UTF8フラグの問題かなと思って、フラグを立てるように変更しました。そしたら、ビンゴで警告が出なくなりました。私が、UTF8フラグをイマイチ理解していないのが根底の問題のようです。

if ($from ne "utf8") {
  from_to($content, $from,"utf8");
}
$content = decode("utf8",$content);