2011-09-12 17 views
1

我正在使用PERL編寫Web爬蟲,並且當我嘗試使用HTML :: Entities :: decode_entities顯示字符串時,我意識到存在奇怪的行爲。如何在Perl中正確顯示HTML實體

我在處理包含中文字符和字符串的字符串,如Jìngyè。 我用HTML :: Entities :: decode_entities來解碼中文字符,效果很好。但是,當字符串不包含中文字符時,字符串顯示不正常(J ngy )。

我寫了一個小代碼來測試2個字符串上的不同行爲。

字符串1是「臺北市中山區九龍三路22號10466」,字符串2是「104臺灣台北市中山區九龍三路20號」。

下面是我的代碼:

print "before: $1\n"; 
my $decoded = HTML::Entities::decode_entities($1."&#34399");#I add the last character just for testing 
print "decoded $decoded\n"; 
my $chopped = substr($decoded, 0, -1); 
print "chopped: $chopped\n"; 

這是我的結果:

前:22號,Jngy三路,中山區區,臺北市,臺灣10466

解放臺灣市中山區吉城三路22號10466號(正確)

切碎:臺北市中山區九龍三路22號10 466(不正確)

前:104臺灣台北市中山區區Jngy三路20號

解碼104臺灣台北市中山區區敬業三路20號號(正確)

斬: 104臺灣台北市中山區長城三路20號(正確)

有人能解釋一下爲什麼會發生這種情況?以及如何解決這個問題,以便我的字符串將正確顯示。

非常感謝。

對不起,我沒有清楚我的問題,下面是我寫的代碼,其中URL是http://maps.google.com/maps/place?cid=10931902633578573013

sub getInfoURLs { 
my ($url) = @_; 
unless (defined $url){ 
    print 'URL was not defined when extracting info\n'; 
    return 0; 
} 

my $contain_request = LWP::UserAgent->new->get($url); 
if($contain_request -> is_success){ 
    my $contain_content = $contain_request -> decoded_content; 

    #store address 
    if ($contain_content =~ m/$address_pattern/i){ 
     print "before: $1\n"; 
     my $decoded = HTML::Entities::decode_entities($1."&#34399"); 
     print "decoded $decoded\n"; 
     my $chopped = substr($decoded, 0, -1); 
     print "chopped: $chopped\n"; 
     #unicode conversion 
     #store in database    
    } 
} 
} 
+0

你有沒有看[這個問題和它的答案(http://stackoverflow.com/questions/2725893/how-do-i-split-chinese-characters-one-by-one)? – MarcoS

+0

你對實體的輸入是什麼樣的?你的例子在箱子中顯示無效字符給我;也許這就是所有的解釋?也許你需要像&實體那樣輸入它們;爲了使標記不吃它們。 – tripleee

+0

對不起,J ngy 中的 已經是替換角色了,您對它進行了不恰當的處理。顯示完整的代碼,以便我們可以自行重現問題。特別有趣的是,$ 1是如何填充的,看起來像是用[Devel :: Peek](http://p3rl.org/Devel::Peek):: Dump()轉儲的。 – daxim

回答

2

首先,一定要使用use strict; use warnings;

問題是你沒有編碼你的輸出。文件句柄只能傳輸字節,但傳遞的是解碼文本。

當你傳遞明顯錯誤的東西時,Perl將輸出UTF-8(-ish)。 chr(0x865F)顯然不是一個字節,所以:

$ perl -we'print "\xE8\x{865F}\n"' 
Wide character in print at -e line 1. 
è號 

但它並不總是顯而易見的,什麼是錯。 chr(0xE8)可能是一個字節,所以:

$ perl -we'print "\xE8\n"' 
� 

轉換一個值的一系列字節的過程被稱爲「序列」。序列化文本的具體情況稱爲字符編碼。

Encode的encode用於提供字符編碼。您也可以使用open模塊自動調用encode

$ perl -we'use open ":std", ":locale"; print "\xE8\x{865F}\n"' 
è號 

$ perl -we'use open ":std", ":locale"; print "\xE8\n"' 
è