这两天在用Perl
写一个程序,从一个网页上抽取出某个表格的内容,然后存起来供日后使用。
取网页用LWP::UserAgent
,分析表格使用HTML::TableExtract
,保存使用Config::General
。然而,在用Config::General
读取它自己存的文件时出了问题,根源在于编码。网页编码是GB2312,而Perl的内部表示使用Unicode,所以Perl把中文字符看成是一系列奇怪的字节,而Config::General
偏偏使用chr(182)作为一个特殊的标志,用来处理Here-Document。当某些中文字符恰好含有这个字节的时候,Config::General
就被骗了。
一度,我只好把数据存为CSV格式。
后来在Advanced Perl Programming第二版上看到6.5节Encode后,把网页内容读入后用decode
处理一下,在print
出去之前再用encode
处理一下,就可以了。而Config::General
保存的文件本身就是Unicode,所以无需使用Encode
来处理。
举个例子
use LWP::UserAgent; use Encode; $browser = new LWP::UserAgent; $response = $browser->get('http://some.where'); $content = decode('euc-cn', $response->content);
这样,一个汉字就会被当成一个字,而不是一系列字节。这里euc-cn就代表gb2312,对于Encode
来说它们是同义词,或者说gb2312是euc-cn的alias。
直接打印经过decode
的字符串会产生警告,去掉警告的方法是再encode
一下,如:
$content = encode('utf8', $content); print $content, "n";
perl5.8.7后可以直接用
$response->decoded_content();
得到utf8编码的网页
果然,我看了一下HTTP/Message.pm,最终还是调用了Encode,不过肯定是用decoded_content好了,一来不怕人家改编码,二来代码也精简。