Mojo::DOM 在 Perl 中破坏 UTF8

And*_*wby 1 perl mojolicious mojo-useragent

我试图找出如何使用Mojo::DOMUTF8 (和其他格式......不仅仅是 UTF8)。它似乎搞乱了编码:

    my $dom = Mojo::DOM->new($html);

    $dom->find('script')->reverse->each(sub {
        #print "$_->{id}\n";
        $_->remove;
    });

    $dom->find('style')->reverse->each(sub {
        #print "$_->{id}\n";
        $_->remove;
    });

    $dom->find('script')->reverse->each(sub {
        #print "$_->{id}\n";
        $_->remove;
    });

    my $html = "$dom"; # pass back to $html, now we have cleaned it up...
Run Code Online (Sandbox Code Playgroud)

这是我在保存文件而不通过 Mojo 运行它时得到的结果:

在此输入图像描述

...然后通过 Mojo 一次:

在此输入图像描述

FWIW,我正在使用 , 抓取 HTML 文件Path::Tiny

my $utf8 = path($_[0])->slurp_raw;

据我了解,应该已经将字符串解码为可供 Mojo 使用的字节?

更新:在布莱恩的建议之后,我研究了如何找出编码类型以正确解码它。我尝试了 Encode::Guess 和其他一些方法,但他们似乎在很多方面都出错了。这似乎可以解决问题:

my $enc_tmp = `encguess $_[0]`;
my ($fname,$type) = split /\s+/, $enc_tmp;
my $decoded = decode( $type||"UTF-8", path($_[0])->slurp_raw );
Run Code Online (Sandbox Code Playgroud)

bri*_*foy 7

您正在读取原始八位字节,但没有对它们进行解码(将原始数据存储在 中$utf8)。然后你把它当作你已经解码了它,所以结果是 mojibake。

\n
    \n
  • 如果您读取原始八位字节,请在使用之前对其进行解码。您最终将得到正确的 Perl 内部字符串。
  • \n
  • slurp_utf8将为您解码。
  • \n
  • 同样,再次输出时也必须编码。在此示例中,编译open指示执行此操作。
  • \n
  • Mojolicious 已经必须Mojo::File->slurp获取原始八位字节,因此您可以减少依赖项列表。
  • \n
\n
use v5.10;\nuse utf8;\n\nuse open qw(:std :utf8);\nuse Path::Tiny;\nuse Mojo::File;\nuse Mojo::Util qw(decode);\n\nmy $filename = 'test.txt';\nopen my $fh, '>:encoding(UTF-8)', $filename;\nsay { $fh } "Copyright \xc2\xa9 2022";\nclose $fh;\n\nmy $octets = path($filename)->slurp_utf8;\n\nsay "===== Path::Tiny::slurp_raw, no decode";\nsay path($filename)->slurp_raw;\n\nsay "===== Path::Tiny::slurp_raw, decode";\nsay decode( 'UTF-8', path($filename)->slurp_raw );\n\nsay "===== Path::Tiny::slurp_utf8";\nsay path($filename)->slurp_utf8;\n\nsay "===== Mojo::File::slurp, decode";\nsay  decode( 'UTF-8', Mojo::File->new($filename)->slurp );\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
===== Path::Tiny::slurp_raw, no decode\nCopyright \xc3\x82\xc2\xa9 2022\n\n===== Path::Tiny::slurp_raw, decode\nCopyright \xc2\xa9 2022\n\n===== Path::Tiny::slurp_utf8\nCopyright \xc2\xa9 2022\n\n===== Mojo::File::slurp, decode\nCopyright \xc2\xa9 2022\n
Run Code Online (Sandbox Code Playgroud)\n

  • @AndrewNewby 该网站(最有可能)在您检索文件时告诉您正确的编码。如果您使用 Perl 来获取它,那么您可以使用服务器的编码自动解码它(例如,如果使用来自 Mojo::UserAgent 的响应,则为“->text”;如果使用 LWP,则为“->decoded_content”)。但是,如果您将内容保存到磁盘而没有标题,则您会丢弃该信息,这就是您现在需要“猜测”它的原因。 (4认同)