文字参照のデコード時にutf8フラグあるなしが混ざるせいで化けてるってことなので、
とりあえず結論としては $tree->parse_file のかわりに
my $html = do { local $/; open my $fh, "<", $tempfile; <$fh> };
$tree->parse(Encode::decode_utf8($html));
とすればとりあえず期待通りに動く。