【问题标题】:Why does Perl's LWP gives me a different encoding than the original website?为什么 Perl 的 LWP 给我的编码与原始网站不同?
【发布时间】:2010-02-26 11:15:15
【问题描述】:

假设我有这个代码:

use strict;
use LWP qw ( get );

my $content = get ( "http://www.msn.co.il" );

print STDERR $content;

错误日志显示类似“\xd7\x9c\xd7\x94\xd7\x93\xd7\xa4\xd7\xa1\xd7\x94” 我猜是utf-16?

网站的编码是用

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1255">

那么为什么出现这些字符而不是 windows-1255 字符?

而且,另一个奇怪的事情是我有两台服务器:

第一台服务器返回 CP1255 字符,我可以简单地将其转换为 utf8, 而当前服务器给了我这些字符,我不能用它做任何事情......

apache/perl/module 中是否有任何配置文件弄乱了编码? 强迫什么...?

我的网站在第二台服务器上的结果是 perl 文件和标题都是 utf8,所以当我编写不是英文字符的文本时,上面示例中的内容显示正常(即使它是奇怪的 utf 字符)但我自己的静态文本看起来像“×ס'××ר××:”

我测试的另一件事是......

通过 perl:

my $content = `curl "http://www.anglo-saxon.co.il"`;    

我得到了 utf8 编码。

通过 Bash:

curl "http://www.anglo-saxon.co.il"

在这里我得到了 CP1255 ( Windows-1255 ) 编码 ...

另外, 当我在 bash 中运行脚本时 - 它提供 CP1255,当通过网络运行时 - 然后又是 utf8 ...

通过将内容从 utf8 更改为应有的内容,然后返回 utf8 来解决问题:

use Text::Iconv;

my $converter = Text::Iconv->new("utf8", "CP1255");
   $content=$converter->convert($content);

my $converter = Text::Iconv->new("CP1255", "utf8");
   $content=$converter->convert($content);

【问题讨论】:

    标签: perl content-encoding lwp windows-1255


    【解决方案1】:

    所有这些手动编码和解码都是不必要的。当 HTML 说页面是在 windows-1255 中编码时,它是在骗你;服务器说它正在提供 UTF-8,它是。归咎于 Microsoft HTML 生成工具。

    不管怎样,由于服务器确实返回了正确的编码,这可行:

    my $response = LWP::UserAgent->new->get("http://www.msn.co.il/");
    my $content = $res->decoded_content;
    

    $content 现在是一个 perl 字符串,可以做任何你需要的事情。如果要将其转换为其他编码,则在其上调用Encode::encode 是合适的; 不要使用Encode::decode,因为它已经被解码过一次。

    【讨论】:

      【解决方案2】:

      http://www.msn.co.il 是 UTF-8 格式,并且正确地表明了这一点。字符串 "\xd7\x9c\xd7\x94\xd7\x93\xd7\xa4\xd7\xa1\xd7\x94" 也是正确的 UTF-8 (להדפסה)。我没发现问题。

      我认为您的第二个问题是由于您混合了不同的编码(UTF-8 和 Windows-1252)。你可能想正确地encode/decode你的字符串。

      【讨论】:

      【解决方案3】:

      首先,请注意您应该从LWP::Simple 导入get。其次,一切正常:

      #!/usr/bin/perl
      use strict; use warnings;
      use LWP::Simple qw ( getstore );
      getstore 'http://www.msn.co.il', 'test.html';
      

      这向我表明问题在于您将输出发送到的文件句柄的编码。

      【讨论】:

        【解决方案4】:

        您提供的具有十六进制值的字符串似乎是 UTF-8 编码。你得到这个是因为 Perl 在处理字符串时“喜欢”使用 UTF-8。 LWP::Simple-&gt;get() 方法自动解码来自服务器的内容,包括撤消任何内容编码以及转换为 UTF-8。

        您可以深入了解内部结构并获得一个更改字符编码的版本(请参阅HTTP::Message's decoded_contentHTTP::Response's decoded_content 使用它,您可以从LWP::UserAgent's get 获得)。但是用你想要的编码重新编码数据可能更容易,比如

        use Encode; 
        ...; 
        $cp1255_bytes = encode('CP1255', decode('UTF_8', $utf8_bytes));
        

        您看到的混合可读/垃圾字符是由于在同一流中混合了多个不兼容的编码。流可能被标记为 UTF-8,但您将 CP1255 编码字符放入其中。您需要将流标记为 CP1255 并仅将 CP1255 编码的数据放入其中,或者将其标记为 UTF-8 并仅将 UTF-8 编码的数据放入其中。提醒自己字节不是字符并在它们之间进行适当的转换。

        【讨论】:

        • 这不完全是答案,但我接受了你的建议使用 Text::Iconv;我的 $converter = Text::Iconv->new("utf8", "CP1255"); $content=$converter->convert($content);我的 $converter = Text::Iconv->new("CP1255", "utf8"); $content=$converter->convert($content);解决了问题....耶!
        • 报错“Cannot decode string with wide characters”表示该字符串已经解码。您使用Text::Iconv 从 UTF-8->CP1255->UTF-8 的转换只有效,因为 Perl 的内部编码是 UTF-8。原始的$content 是一个字符串(根据您从解码中得到的错误消息),但您应该将一个字节字符串传递给convert。如果这是您想要的,您可能只需执行 encode('UTF-8',$content) 即可获得 UTF-8 字节字符串。
        猜你喜欢
        • 2012-09-30
        • 1970-01-01
        • 1970-01-01
        • 2011-04-30
        • 2010-10-29
        • 2020-12-17
        • 2013-02-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多