SLY_G
@SLY_G
журналист, переводчик, программист, стартапщик

Портится кодировка скачанных perl-скриптом данных при добавлении в базу?

Перешёл на новый хостинг, система та же осталась, freebsd, и один из скриптов перестал работать.



Он скачивает данные с другого https сайта и сохраняет их в базу.

Данные в кодировке cp1251, база, таблицы и соединение mysql в той же кодировке.



my.cnf:



character-set-server=cp1251
    collation-server=cp1251_general_ci
    init-connect="SET NAMES cp1251"




Когда соединяюсь с базой из скрипта, выполняю:



$dbh->do('SET CHARACTER SET cp1251');<br>



Данные выкачиваются так:



$ua = new LWP::UserAgent;<br>
    ....<br>
    $res = $ua->get(....)<br>
    $s = $res->decoded_content();<br>
<br>




Потом перменная $s парсится и результат вставляется в базу. И в базе кодировка испорченная:

Ñáåðáà íê ÐÔ (ÌÑÊ), ïîïîëíåíèå



Очень странную вещь обнаружил, ковыряясь со скриптом. Если просто сохранить полученные данные в текстовый файл, потом их из этого же файла прочесть и вставить в базу — кодировка не портится!



Если просмотреть этот текстовый файл, видно что кодировка там правильная, cp1251



Что изменилось с предыдущего хостинга:



perl: было 5.10.1, стало 5.14.4

libwww: было 5.835, стало 6.05

mysql server как был, так и остался 5.1



UPDATE: Только что обнаружил. Если вместо $res->decoded_content() написать $res->content(), то всё работает.

Возможно, из-за того, что у скачиваемой страницы нет в заголовках charset.

Но я всё равно не понимаю, что происходит со строкой, что если её в базу вставить, она в неправильной кодировке, а если в файл записать — то в правильной. То ли utf-флаг какой-то ставится? Не понимаю :(
  • Вопрос задан
  • 4546 просмотров
Решения вопроса 1
vsespb
@vsespb
> Возможно, из-за того, что у скачиваемой страницы нет в заголовках charset.
или наоборот, есть.

> Если просто сохранить полученные данные в текстовый файл, потом их из этого же файла прочесть и вставить в базу — кодировка не портится!
хорошо бы увидеть код как читали, как писали.

> Если просмотреть этот текстовый файл, видно что кодировка там правильная, cp1251
это ещё ничего не доказывает )

По идее нужно знать как работает unicode

perldoc.perl.org/perlunitut.html
perldoc.perl.org/perluniintro.html
perldoc.perl.org/perlunifaq.html

habrahabr.ru/post/190584/

так же включить use strict, use warnings.

А так же в нужных местах делать Dump данных модулем Devel::Peek, а потом уже можно будет понять где баг. Ещё хорошо бы все используемые опции DBD::mysql видеть.

Пока что у меня впечатление что Ваш код не работает правильно с текстовыми строками perl, вместо этого использует везде legacy однобайтовую кодировку. Так тоже можно, тогда нужно использовать content а не decoded_content, раньше возможно работало, т.к. старая версия LWP не понимала кодировку именно этой страницы и вызов decoded_content был эквивалентен content. Непонятно правда, почему после чтения и записи из файла данные меняются. Впрочем на это могут повлиять опции, которые Вы используете при работе с файлами.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
vsespb
@vsespb
del
Ответ написан
Комментировать
@kirichenko
decoded_content() — во-первых разжимает gzip/deflate, во вторых, переводит из реальной кодировки (которую сумел определить) в utf-8 (во внутреннем представлении перла). Чтоб с кодировкой махинаций не было, можно вот так делать:

decoded_content(charset=>'none')

в общем, прежде, чем задавать такие вопросы, неплохо бы было почитать документацию
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы