解决Perl 5.8.8用XML::RSS无法解析非utf-8编码的RSS问题

解决Perl 5.8.8用XML::RSS无法解析非utf-8编码的RSS问题

摘要:XML-RSS-1.36是 常用的操作RSS的模块,不过遗憾的是,不支持gb2312,big5等编码的rss文件,操作的话直接报错“Couldn't open encmap gb2312.enc”退出。今天一段代码读baidu的新闻rss 时遇到这个问题,先鄙视一下他用gb2312编码。网上搜索到的解决方案在我这里无效,最终自己比较不优雅的解决了一下。      

      这个问题发生的原因是XML::RSS模块会调用XML::Parser模块,最终是调用的Perl的核心库Expat,这东西是C写的,不支持gb2312编码。网上搜索到的解决办法如下:
      1. Download GB2312.TXT from ftp.unicode.org,事实上这个东西目前下载地址是http://search.cpan.org/src/GUS/Unicode-UTF8simple-1.06/gb2312.txt      
      2. Download the XML::Encoding 1.01 and get two binaries: make_encmap and compile_encoding,这东西在d:\perl\bin下面,根据的安装目录而有变化。
      3. run make_encmap as follows:make_encmap GB2312 GB2312.TXT > GB2312.encmap
      4. Add expat='yes' to the first line of GB2312.encmap
      5. run compile_encoding: compile_encoding -o GB2312.enc GB2312.encmap
      6. copy GB2312.enc to /usr/lib/perl5/site_perl/5.005/i386-linux/XML/Parser/Encoding,windows的话,lib/下面自己去找。

      不过遗憾的是,现在这种方法已经不行了,最后在<<Thinking in perl>>中找到原因,如下:
      使用 make_enmap 的时候需要改下载来的GB2312.TXT。因为在 GB2312.txt  中,中文编码0x2121  的应该为 0xa1a1 , 即第一列值全部需要加 0x8080,这样就可以了。修改 make_enmap给需要处理的地方每个值加 0x80。

      不过这样还是太麻烦了,我的做法是直接给XML文件编码一下,代码片段如下:
  • $xml = get( 'http://news.baidu.com/n?cmd=1&class=internet&tn=rss⊂=0' );
  • if( ! defined($xml) )
  • {
  • warn "$!n";
  • return;
  • }
  • if( $xml =~ /s+encoding="(.*?)"/ )
  • {
  • $encode = $1;
  • }
  • if ( &trim($encode) eq "" )
  • {
  • print "No encode found, use utf-8.n";
  • }
  • if( ($encode ne "") && ($encode ne "utf-8") && ($encode ne "UTF-8") )
  • {
  • $xml = decode_utf8( decode( $encode, $xml ) );
  • }
  • $xml =~ s/encoding="(.*?)"/encoding="utf-8"/;
  • my $rss = new XML::RSS;
  • $rss->parse($xml);
      
      先抓取RSS数据,然后查询编码,不是utf-8的话,自己解码再编码到utf-8,并且记得要替换xml文件中的编码申明。
自己动手,丰衣足食。