Perl LWP::UserAgent 错误处理 UTF-8 响应
Posted
技术标签:
【中文标题】Perl LWP::UserAgent 错误处理 UTF-8 响应【英文标题】:Perl LWP::UserAgent mishandling UTF-8 response 【发布时间】:2011-06-02 02:27:24 【问题描述】:当我使用 LWP::UserAgent 检索以 UTF-8 编码的内容时,LWP::UserAgent 似乎无法正确处理编码。
这是通过命令chcp 65001
将命令提示符窗口设置为 Unicode 后的输出注意,这最初看起来一切都很好,但我认为这只是外壳重新组装字节并解码 UTF-8,从另一个输出你可以看到 perl 本身没有正确处理宽字符。
您可以在上面看到有效负载长度是 31 个字符,但 Perl 认为它是 33 个字符。 为了确认,在十六进制中,我们可以看到 UTF-8 序列 c49b 和 c3bd 被解释为四个单独的字符,而不是两个 Unicode 字符。
这是代码
#!perl 使用严格; 使用警告; 使用 LWP::UserAgent; 我的 $ua = LWP::UserAgent->new(); 我的 $response = $ua->get('http://localhost/Bud.xml'); if (!$response->is_success) die $response->status_line; print '='x70,"\n",$response->as_string(), '='x70,"\n"; 我的 $r = $response->decoded_content((charset => 'UTF-8')); $/ = "\x0d\x0a"; # 似乎是 \x0a 否则! 咀嚼($r); # 删除任何 xml 序言 $r =~ s/^\x0d\x0a//; print "响应内容长度为", length($r), "\n\n"; 打印“....v....1....v....2....v....3....v....4\n”; 打印 $r,"\n"; 打印 ".. . . v . . . . . 1 . . . . . v . . . . 2 . . . . v . . . . 3 . . . . \n"; 打印解包(“H*”,$r),“\n”; 打印连接(“”,拆分(“”,$r)),“\n”;请注意,Bud.xml 是 UTF-8 编码的,没有 BOM。
如何说服 LWP::UserAgent 做正确的事?
附言最终我想将 Unicode 数据转换为 ASCII 编码,即使这意味着用 一个 问号或其他标记替换每个非 ASCII 字符。
更新 1
我接受了 Ysth 的“升级”答案——因为我知道在可能的情况下这样做是正确的。但是,有一种解决方法可以将数据修复为格式良好的 Perl Unicode 字符串。
$r = decode("utf8", $r);
更新 2
我的数据被馈送到一个非 Perl 应用程序,该应用程序使用 Code Page 437 将数据显示到多个位置的 Putty/Reflection/Teraterm 终端。该应用当前显示如下内容:
Bud├ä┬øjovick├â┬¢ Budvar
我将使用($r = decode("UTF-8", $r)) =~ s/[\x80-\xFFFF]/\xFE/g;
来显示应用:
布德■约维克■布德瓦
摆脱 CP437 将是一项重大工作,因此在中短期内不会发生这种情况。
更新 3
CPAN 有一些有趣的 Unicode 模块,例如:
文本::Unidecode Unicode::Map8 Unicode::地图 Unicode::Escape Unicode::音译Text::Unidecode 将“Budějovický Budvar”翻译成“Budejovicky Budvar”——在我看来,语音音译的尝试并不特别令人印象深刻,但我不会说捷克语。不过,说英语的人可能更喜欢“Bud■jovick■ Budvar”。
【问题讨论】:
进行完整性检查,您使用的是什么版本的 LWP? @ysth LWP::UserAgent 2.036 版,LWP 5.808 版 您所说的将 21 位 Unicode 数据转换为 7 位 ASCII 数据的最终目标令人沮丧,因为我自己在将大约 100k 文档均质化为 Unicode 时遇到了不小的麻烦。在 11,542 个文档中,10,997 个使用 UTF-8 (95.39%),539 个使用 ISO-8859-1 (4.67%),5 个使用 Shift_JIS (0.04%),仅 1 个使用 Windows-1252 (0.0087%) .您希望集中在 21 位字符上,而不是 7 位字符上!欢迎来到新千年,它的第二个十年即将在不到 5 小时内开始。 单播到带有?
的事物的另一个问题是,在标准文档中非常 特别不建议执行此特定操作.您无法将有效的?
与无效的?
区分开来。 C0 控制代码在这里可能很有用。字符 1A 是 SUBSTITUTION 字符,它在 ASCII 中的工作方式与 U+FFFD REPLACEMENT CHARACTER 在 Unicode 中的工作方式非常相似。 1A 表示“最初打算用作传输控制字符,以指示已收到乱码或无效字符。” U+FFFD 现在为我们履行了这项职责。请不要单播您的数据。
@tchrist:请参阅问题末尾的更新,我认为最后一个稍微好一些。 Putty 忽略了 \x1A,所以我使用了 \xFE (■),因为我觉得给出一些缺失字符的视觉指示会更好。
【参考方案1】:
升级到更新的 libwwwperl。您使用的旧版本仅支持 text/* 内容类型的 decoded_content 的 charset 参数;较新的版本也适用于 application/xml 或任何以 +xml 结尾的内容。
【讨论】:
以上是关于Perl LWP::UserAgent 错误处理 UTF-8 响应的主要内容,如果未能解决你的问题,请参考以下文章
为啥当我使用 Perl 的 REST::Client 发送 POST 请求,而不是使用 Perl 的 LWP::UserAgent 或 Python 时,我得到“405: Method Not All
未通过 https 使用 LWP::UserAgent get() 获取预期内容
为啥 LWP::UserAgent 是通过 require LWP::UserAgent 而不是使用 LWP::UserAgent 导入的?