Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: lwp utf-8 перегнать в cp1251  (Прочитано 26449 раз)
0 Пользователей и 1 Гость смотрят эту тему.
samlab
Гость
« : 04-10-2010 23:12 » 

Приветствую всех. Собственно, всю ночь бился над такой задачей, никак не могу ее решить. Есть сайт в utf-8 кодировке, пытаюсь ее получить вот таким вот образом - вместо русских букв вытаскиваю кракозябры...
Код: (Perl)
#!/usr/bin/perl -w

$| = 1;

use LWP::UserAgent;
use LWP::ConnCache;

my $ua = LWP::UserAgent->new;
$ua->conn_cache(LWP::ConnCache->new());
$ua->agent('MY BOT');
$ua->default_header('X-Forwarded-For' =>"$ip");
$ua->default_header('X-Real-IP' =>"$ip");
$ua->default_header('Referer' => "http://mysite.info/");
$ua->default_header('Accept-Encoding' => "gzip,deflate");
$ua->default_header('Accept-Language'=> "en-us");
$ua->default_header('Accept'=> "text/html,*/*");
$ua->default_header('Accept-Charset' => "utf-8");

$response = $ua->get('http://site.ru/');

print $response->decoded_content(charset => 'UTF-8');
Подскажите, пожалуйста, как следует поступить...
« Последнее редактирование: 21-04-2011 06:55 от McZim » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 05-10-2010 03:46 » 

samlab, указание предпочтений не гарантирует возврат именно в этой кодировке, равно как и автоматическую перекодировку.
Следует смотреть в ответе следующие места:

1. В заголовке HTTP-ответа, поле Content-Type. Там указан тип документа, но в доп. параметре может быть (как правило, но не обязательно) и кодировка.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17

В принципе, можно ограничиться только этим пунктом, но если хочется поддержать и криворуких админов, то см. п.2.

2. Если в п.1. указан text/html, то можно распарсить контент и просмотреть наличие в заголовке HTML тега^

Код:
<meta http-equiv="Conetnt-Type" content="text/html; charset=....." />

Найденную кодировку можно использовать для перекодирования исходного контента.

Этого уже должно быть более чем достаточно, но есть еще более криворукие админы и для них есть п.3.

3. Кодировку можно попытаться определить, анализируя непосредственно контент.
Во-первых, посмотри в инете способы автоопределения UTF-16 (крайне редкий случай применения, но встречал)  и UTF-8 (с BOM и без).  Вероятность встретить UTF-32 стремится к нулю. На эти кодировки надо тестировать с самого начала.
Если это не Unicode, то это 8-битная кодировка. Вычисли гистограмму распределения символов по кодам и еще одну - по типам (цифра, знак, пробел, большие/маленькие латинские, большие/маленькие локальные, символы из верхнего диапазона. На основе их анализа и будешь принимать решение. Первую можно построить один раз, а вторую надо делать для каждой тестируемой кодировки.
Например, latin1 будет 99-100% укладываться в диапазон 1..127 (возможны редкие символы в диапазоне 128-255).
Многие 8-битные кодировки будут иметь значительную долю в "большие/маленькие локальные".
Определить таки кодировку точно невозможно. По этому должна быть таблица предпочтений - приоритетов проверяемых кодировок.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
samlab
Гость
« Ответ #2 : 05-10-2010 17:21 » 

Спасибо. Кодировка точно ютф-8, но вот в чем траблы. Когда распечатываются данные в консоль, то возникает байда вот такого плана
Код:
Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

C:\Documents and Settings\Саша>cd Рабочий стол

C:\Documents and Settings\Саша\Рабочий стол>test.pl
Wide character in print at C:\Documents and Settings\╤р°р\╨рсюўшщ ёЄюы\test.pl l
ine 47.
document.writeln('<a href="" class=""><b>╨Ю╨┐╨╗╨░╤З╨╡╨╜╨╜╨
░╤П ╨а╨╡╨║╨╗╨░╨╝╨░:</b></a>'+'<br><a href="" class="" target=_top oncl
ick="javascript: f52126(this);">╨Р╨▓╤В╨╛ ╨╕╨│╤А╨╛╨║ - ╨│╤А╨╛╨╖╨░ ╨║╨░╨╖╨╕╨╜╨╛! <
/a><br><a href="" class="" target=_top onclick="javascript: f52126(thi
s);">╨з╤В╨╛ ╨╜╤Г╨╢╨╜╨╛ ╨╖╨╜╨░╤В╤М ╤В╤А╨╡╨╣╨┤╨╡╤А╤Г ╨┤╨╗╤П ╤Г╤Б╨┐╨╡╤И╨╜╨╛╨╣ ╤А╨░╨
▒╨╛╤В╤Л ..</a><br>function f5212(a715) {a7
1580.href += "&pg=http://site.info/";}
C:\Documents and Settings\Саша\Рабочий стол>
Если же сохранять ответ в файл, то там все нормально читается, вместо кракозябров русские буквы...
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 05-10-2010 17:37 » 

С этого и надо было начинать. Виндовая консоль работает с так называемой кодировкой OEM. По сути, это кодировка MSDOS. Для русской локали это cp866. Перекодируй перед выводом. См. документацию IO::File и PerlIO::encoding. Для stdin/stdout можно сделать так:

Код: (Perl)
use open 'IN' => ':encoding(cp866)', 'OUT' => ':encoding(cp866)';

Насчет указанной кодировки в примере: это только пример - я не тестировал. Кодировки см в модуле Encode.

Поддерживаемые кодировки:

Код: (Perl)
perl -e 'use Encode; print join("\n", Encode->encodings(":all")), "\n";'
« Последнее редактирование: 21-04-2011 06:56 от McZim » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
samlab
Гость
« Ответ #4 : 05-10-2010 17:53 » 

Спасибо, все сделал!
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 05-10-2010 17:53 » 

Работает?  Меня одолевают смутные сомнения
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 05-10-2010 18:42 » 

В общем, если кому еще понадобится: http://perldoc.perl.org/PerlIO.html

Код: (Perl)
use Encode;

binmode(STDOUT, ':encoding(cp866):bytes');
print "Йцукенг\n";

Если до print стоит "use utf8", либо Perl запущен с ключем "-CO", то print может генерировать предупреждение:

Цитата
Wide character in print at file line line_number

Для подавления в блоке с print, перед ним можно поставить определение "use bytes".
Директивы "use utf8" и "use bytes" влияют на распознание кодировки UTF-8 строковых констант в тексте программы.
« Последнее редактирование: 21-04-2011 06:56 от McZim » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
samlab
Гость
« Ответ #7 : 05-10-2010 23:19 » 

Ага, все работает, через use Encode сделал, на cpan нашел пример использования, спасибо за помощь, RXL.
Код: (Perl)
$mess = $response->decoded_content(charset => 'utf-8');
$octets = encode("cp866", $mess);
« Последнее редактирование: 21-04-2011 06:56 от McZim » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 06-10-2010 03:27 » new

Таки пока не за что...
Вопрос о переносимости: а если твою программу понадобится запустить на другой платформе?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
samlab
Гость
« Ответ #9 : 06-10-2010 17:38 » 

Как же, как же, как раз есть за что...  Улыбаюсь
А по поводу переносимости, я уже отказался от поставленной перед собой задачи, скажем так, идея себя изжила... Просто попробовал, работает и все...
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 20-04-2011 12:36 » 

Вновь мне понадобилось перекодировать. Пишу, чтобы было где найти Улыбаюсь

Код: (Perl)
use Encode;

# Перекодировка строки из cp1251 в UTF-8.
$str = encode('utf8', decode('cp1251', $str));

decode() переводит строку из указанной кодировки во внутреннюю кодировку Perl (обычно это UTF-8).
encode() переводит из внутренней кодировки в указанную.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines