Правильный способ получить веб-сайт в кодировке ISO-8859-1 с помощью LWP :: UserAgent?

Я получаю веб-сайт в кодировке «ISO-8859-1» с помощью «LWP :: UserAgent» со следующим кодом.

Проблема в том, что специальные символы отображаются неправильно, особенно знак «€» отображается неправильно.

Кодировка контента распознается как «ISO-8859-1», что правильно.

Чтобы отобразить полученный текст, я сохраняю его в файл и открываю с помощью Notepag ++.

Вопрос: Как правильно получить специальные символы в кодировке «ISO-8859-1»?


#SENDING REQUEST
my $ua = LWP::UserAgent->new();
$ua->agent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1'); # pretend we are very capable browser

my $req = HTTP::Request->new(GET => $url);

#add some header fields
$req->header('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
$req->header('Accept-Language', 'en;q=0.5');
$req->header('Connection', 'keep-alive');
$req->header('Host', 'www.url.com');

#SEND
my $response = $ua->request($req);

#decode  trial1
print $response->content_charset(); # gives ISO-8859-1 which is right
my $content  = $response->decoded_content(); #special chars are displayed wrong

#decode trial2
my $decContent =  decode('ISO-8859-1', $response->content());
my $utf8Content = encode( 'utf-8', $decContent ); #special char € is displayed as Â

#decode trial3
Encode::from_to($content, 'iso-8859-1', 'utf8'); #special char € is displayed as  too


#example on writing data to file
open(MYOUTFILE, ">>D:\\encodingperl.html"); #open for write, overwrite
print MYOUTFILE "$utf8Content"; #write text
close(MYOUTFILE);



person Skip    schedule 04.11.2012    source источник
comment
Вы забыли установить кодировку вывода на utf8, изменив дескриптор вывода.   -  person tchrist    schedule 04.11.2012


Ответы (2)


Как и любой другой:

my $content = $response->decoded_content();

При этом кодировка iso-8859-1 не включает знак евро. Вероятно, у вас действительно есть cp1252. Вы можете исправить это следующим образом:

my $content = $response->decoded_content( charset => 'cp1252' );

Вторая проблема заключается в том, что вы не кодируете свой вывод. Вот как бы вы это сделали.

open(my $MYOUTFILE, '>>:encoding(cp1252)', 'D:\\encodingperl.html')
   or die $!;
print $MYOUTFILE $content;

Используйте подходящую для вас кодировку (например, UTF-8), если она не cp1252, которую вы хотите. Если вы хотите, чтобы исходный файл был в исходной кодировке, используйте

my $content = $response->decoded_content( charset => 'none' );

и

open(my $MYOUTFILE, '>>', 'D:\\encodingperl.html')
   or die $!;
binmode($MYOUTFILE);
print $MYOUTFILE $content;
person ikegami    schedule 04.11.2012
comment
Я не понимал, что decoded_content имеет этот charset параметр; Я собирался предложить использовать content плюс руководство Encode::decode. В любом случае, это правильный ответ, с оговоркой, что кодировка может быть ISO-8859-15, а не cp1252. - person hobbs; 04.11.2012
comment
@hobbs, я не понимаю как. iso-8859-15 - это A4. Браузер отобразит A4 как ¤, если ему будет сказано, что это iso-8859-1. Единственный способ, которым браузер отобразил бы €, когда ему сказали, что это iso-8859-1, - это если бы он обнаружил 80, cp1252's €. Имейте в виду, что cp1252 является расширенным набором iso-8859-1. - person ikegami; 04.11.2012
comment
@hobbs, никогда не используйте content. Это не избавляет от сжатия. Если вы хотите декодировать вручную, вы должны использовать my $content = decode(..., $response->decoded_content( charset => 'none' ));. - person ikegami; 04.11.2012
comment
Такие проваленные веб-сайты настолько распространены, что спецификация HTML5 предписывает браузерам предполагать, что любой веб-сайт, который сообщает о своем содержании как ISO-8859-1 лжет и предположим, что это на самом деле Windows-1252. - person cjm; 04.11.2012
comment
@cjm, круто, я не знал, что поведение браузеров стандартное. Отображение символа евро для € также продиктовано HTML5? - person ikegami; 04.11.2012

ISO-8859-1 не имеет символа евро. Если вам нужен символ евро, вы должны использовать ISO-8859-15 или, что еще лучше, UTF-8.

person Olaf Dietsche    schedule 04.11.2012
comment
Спасибо, но это не мой сайт, поэтому кодировку ISO-8859-1 я не могу изменить. Каким-то образом браузеры отображают € правильно, даже если его нет в ISO-8859-1. Есть ли способ преобразовать всю строку в UTF8 с сохранением знаков €? - person Skip; 04.11.2012
comment
Браузеры отображают символ евро с ISO-8859-1 в позиции 128. Это удобно, но технически неправильно. Что может сработать, так это перекодирование ISO-8859-1 в ISO-8859-15, замена всех символов евро 128 на 164 (знак евро в ISO-8859-15) и перекодирование в UTF-8. - person Olaf Dietsche; 04.11.2012