Найти - Пользователи
Полная версия: Очередной вопрос по кодировкам на понимание.
Начало » Python для новичков » Очередной вопрос по кодировкам на понимание.
1
corpse
Доброго времени суток!

Недавно столкнулся с необходимостью написать небольшой парсер одного вебресурса. Использовал 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) выдаёт ту же самую ошибку.

Подскажите пожалуйста, в чём может быть проблема?
corpse
Ах да, забыл. coding в начале файла тоже указал utf-8 - не помогло никак.
Piton23
grpname.decode('utf-8') тож не помогает говоришь?
corpse
Да. Соврешенно аналогичная ошибка:
  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')) по-прежнему заканчиваются ошибкой и пайтон по-прежнему верит, что обе эти строки в юникоде.
py.user.next
corpse
res = BeautifulSoup(urlopen(url).read())
grpname = c.contents[0].string
выведи type(grpname)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB