Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 24, 2012 17:25:25

corpse
От:
Зарегистрирован: 2010-03-27
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Очередной вопрос по кодировкам на понимание.

Доброго времени суток!

Недавно столкнулся с необходимостью написать небольшой парсер одного вебресурса. Использовал urlopen из urllib2 и BeautifulSoup. Кодировка ресурса - utf-8, кодировка локали - тоже utf-8 (debian). Текстовые значения прекрасно обрабатываются, выводятся на экран, но только до того момента, когда их необходимо записать в файл или применить encode/decode.

Значение переменной grpname получаю следующим образом:

res = BeautifulSoup(urlopen(url).read())
grpname = c.contents[0].string
Для примера я вывожу переменную, полученную в результате парсинга и тот же самый текст, набранный мной в одном кортеже:

>>>print (grpname, u'Сортовой прокат')
(u'\u0421\u043e\u0440\u0442\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u043a\u0430\u0442', u'\u0421\u043e\u0440\u0442\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u043a\u0430\u0442')
Как видим, они отображаются идентично. Теперь сделаем например, encode для набранного вручную текста:
>>>print (grpname, u'Сортовой прокат'.encode('utf-8'))
(u'\u0421\u043e\u0440\u0442\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u043a\u0430\u0442', '\xd0\xa1\xd0\xbe\xd1\x80\xd1\x82\xd0\xbe\xd0\xb2\xd0\xbe\xd0\xb9 \xd0\xbf\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0\xd1\x82')
encode прошёл без проблем. А теперь произведём ту же операцию для первой переменной:
>>>print (grpname.encode('utf-8'), u'Сортовой прокат'.encode('utf-8'))
Логичным было бы предположить, что мы должны для переменной получить тот же результат, тем не менее, получаем ошибку:
    print (grpname.encode('utf-8'), u'Сортовой прокат'.encode('utf-8'))

Traceback (most recent call last):
File "test.py", line 49, in pctg
print (grpname.encode('utf-8'), u'Сортовой прокат'.encode('utf-8'))
File "/usr/lib/pymodules/python2.6/BeautifulSoup.py", line 430, in encode
return self.decode().encode(encoding)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)
Этот момент не мне понятен, ведь судя по первому выводу python “понимает”, что строка у нас в юникоде? Или возможно для BeautifullSoup нужны какие-то особые параметры? Печать переменной на экран проходит корректно, а вот например, print str(grpname) выдаёт ту же самую ошибку.

Подскажите пожалуйста, в чём может быть проблема?



Офлайн

#2 Фев. 24, 2012 17:32:19

corpse
От:
Зарегистрирован: 2010-03-27
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Очередной вопрос по кодировкам на понимание.

Ах да, забыл. coding в начале файла тоже указал utf-8 - не помогло никак.



Офлайн

#3 Фев. 24, 2012 21:46:11

Piton23
От:
Зарегистрирован: 2011-10-17
Сообщения: 139
Репутация: +  5  -
Профиль   Отправить e-mail  

Очередной вопрос по кодировкам на понимание.

grpname.decode('utf-8') тож не помогает говоришь?

Офлайн

#4 Фев. 25, 2012 07:28:38

corpse
От:
Зарегистрирован: 2010-03-27
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Очередной вопрос по кодировкам на понимание.

Да. Соврешенно аналогичная ошибка:

  File "test.py", line 53, in pctg
print grpname.decode('utf-8')
File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)
Проблему решил уже вставкой следующего кода в начало:
import codecs
import sys
streamWriter = codecs.lookup('utf-8')[-1]
sys.stdout = streamWriter(sys.stdout)
И при выводе итоговых строк, я добавил u в начале:
print u'INSERT INTO `tovar` (`id`, `num`, `group`, `name`, `gost`, `mark`, `size`) VALUES (%d, %d, %d, "%s", "%s", "%s", "%s");' % (int(id), int(num), int
(grp), name, gost, mark, size)
print u'INSERT INTO `cmetgrps` (`id`, `name`) VALUES (%d, "%s");' % (grp, grpname)
После этого стало возможным без ошибок перенаправить поток вывода средствами ос в файл
./test.py > filename

До этих манипуляций при запуске сваливались всё с той же ошибкой. Проблема решена, тем не менее ответ на вопрос меня всё ещё интересует. Игры с двумя якобы идентичными строками вроде print (grpname.encode('utf-8'), u'Сортовой прокат'.encode('utf-8')) по-прежнему заканчиваются ошибкой и пайтон по-прежнему верит, что обе эти строки в юникоде.



Отредактировано (Фев. 25, 2012 07:30:46)

Офлайн

#5 Фев. 28, 2012 01:22:30

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10010
Репутация: +  857  -
Профиль   Отправить e-mail  

Очередной вопрос по кодировкам на понимание.

corpse
res = BeautifulSoup(urlopen(url).read())
grpname = c.contents[0].string
выведи type(grpname)



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version