I provided some relevant info on encoding/decoding text in this response: https://stackoverflow.com/a/34662963/2957811
To add to that here, it’s important to think of text in one of two possible states: ‘encoded’ and ‘decoded’
‘decoded’ means it is in an internal representation by your interpreter/libraries that can be used for character manipulation (e.g. searches, case conversion, substring slicing, character counts, …) or display (looking up a code point in a font and drawing the glyph), but cannot be passed in or out of the running process.
‘encoded’ means it is a byte stream that can be passed around as can any other data, but is not useful for manipulation or display.
If you’ve worked with serialized objects before, consider ‘decoded’ to be the useful object in memory and ‘encoded’ to be the serialized version.
'xc1xe5xebxe0xff xffxe1xebxfbxedxff xe3xf0xeexecxf3'
is your encoded (or serialized) version, presumably encoded with cp1251. This encoding needs to be right because that’s the ‘language’ used to serialize the characters and is needed to recreate the characters in memory.
You need to decode this from it’s current encoding (cp1251) into python unicode characters, then re-encode it as a utf8 byte stream. The answerer that suggested d.decode('cp1251').encode('utf8')
had this right, I am just hoping to help explain why that should work.
-
-
February 6 2011, 10:41
Вечно путаюсь в этих кодировках, поэтому решил сделать себе памятку. Покажу на примере.
Итак, кодировка исходного кода задается в первой-второй строке:
#-*-coding: UTF-8 -*-
Далее, допустим мы парсим какой-то сайт в windows-1251:
raw_data = urllib.urlopen(«bla bla bla»).read()
Мы получили данные, и сейчас они находятся в кодировке 1251, а исходник в utf-8, и нам нужно воспользоватся регулярками с кириллицей чтобы что-нибудь найти, выражение:
data = re.findall(r’Данные.*?<.*?>(.*?)</>’, raw_data)
выдаст нам пустой массив, потомому что данные в 1251 а регулярка в utf-8. В питоне есть несколько функций для перекодирования:
decode(‘WINDOWS-1251’) — декодирует строку из кодировки 1251 в ЮНИКОД(ЮНИКОД != UTF-8)
encode(‘UTF-8’) — кодирует строку из юникода в UTF-8.
Что касается Юникод vs UTF-8, то:
UNICODE: u’u041cu0430u043cu0430 u043cu044bu043bu0430 u0440u0430u043cu0443′
UTF-8: ‘xd0x9cxd0xb0xd0xbcxd0xb0 xd0xbcxd1x8bxd0xbbxd0xb0 xd1x80xd0xb0xd0xbcxd1x83’
нормальный вид: ‘Мама мыла раму’
Итак, чтобы у нас не было проблем с кодировками, нам достаточно сделать вот так:
raw_data = urllib.urlopen(«bla bla bla»).read().decode(‘WINDOWS-1251’).encode(‘UTF-8’)
И теперь наша запарсеная страница в той же кодировке что и исходник программы, и можно смело использовать кириллицу в регулярках, или в других ваших решениях. Конечно это не единственное решение, но в моем случае самое простое и удобное.
Я, и пожалуй это не удивительно, люблю аниме, как и многие в современном мире. Единственное — терпеть не могу русскую озвучку и предпочитаю смотреть с субтитрами. Но…большинство релизеров сидят на windows и совершенно не думаю о том, что существуют других ОС, для которых кодировка windows-1251 не то что не является родной, но и вообще корректно не отображается. Начав не так давно изучать python, стал думать о различных, полезных для «дома» скриптах, а прочитав на днях статью на хабре Приводим русские тексты на Mac OS X в одну кодировку Python-скриптом, как то оно меня подтолкнуло к написанию простенького скрипта, который бы этим и занимался. О нём и расскажу.
Сам скрипт достаточно простенький и небольшой, вот листинг:
#!/usr/bin/python # -*- coding: utf-8 -*- import os import sys import chardet def converter(filePath): if any([filePath.endswith(extension) for extension in '.srt,.ass,.txt'.split(',')]): with open(filePath, "rb") as F: text = F.read() enc = chardet.detect(text).get("encoding") if enc and enc.lower() != "utf-8": try: text = text.decode(enc) text = text.encode("utf-8") with open(filePath, "wb") as f: f.write(text) print u"%s сконвертирован." % filePath except: print u"Ошибка в имени файла: название содержит русские символы." else : print u"Файл %s находится в кодировке %s и не требует конвертирования." % (filePath, enc) print '-'*40 if __name__ == '__main__': if len(sys.argv[1:]) == 0: try: path = raw_input(u"Input path or file:") except KeyboardInterrupt: print u"Ввод отменён." sys.exit(0) else: path = sys.argv[1:][0] if os.path.isdir(path): last = path[-1] if last.endswith('/'): path = path else : path = path+"/" print path for (path, dirs, files) in os.walk(path): for file in files: filePath = path+file filePath = filePath.decode("utf-8") converter(filePath) elif os.path.isfile(path) : converter(path) sys.exit(0)
Скрипт проверяет входной файл на кодировку, если файл в кодировке, отличной от UTF-8 — конвертирует файл. Для корректной работы скрипта нам необходим модуль chardet. Его нужно скачать, ну а дальше всё просто — разархивируем модуль, через консоль заходим в эту директорию, допустим:
cd ~/Downloads/chardet-2.1.1
и выполнить команду:
python setup.py install
модуль достаточно быстро установится и скрипт будет полностью работоспособен.
Скрипт способен конвертировать как одиночный файл, так и всю директорию целиком (находя в ней только файлы с расширением srt, ass, txt). Примеры:
python converter.py '~/Downloads/Новая папка/ansi.srt'
python converter.py '~/Downloads/Новая папка/'
Если вызвать скрипт без аргументов, то вы получите приглашение ввести путь к директории или файлу.
Пользуйтесь на здоровье.
Скрипт на github где жду ваших фиксов и дополнений.
45 / 39 / 24 Регистрация: 29.11.2013 Сообщений: 139 |
|
1 |
|
Как перекодировать строку?21.12.2014, 18:13. Показов 18409. Ответов 6
Как перекодировать эту строку в читаемый вид из cp1251 в utf-8? ÀÍÅÊÄÎÒ — Ñåìüÿ.Ìóëüò.Ïîäðîáíåå
__________________
0 |
2738 / 2341 / 620 Регистрация: 19.03.2012 Сообщений: 8,832 |
|
21.12.2014, 18:30 |
2 |
Когда строка уже в виде крокозябр и начальная кодировка в которой все нормально отображается потеряна, то только с помощью сервисов типа http://www.artlebedev.ru/tools/decoder/
0 |
45 / 39 / 24 Регистрация: 29.11.2013 Сообщений: 139 |
|
21.12.2014, 18:39 [ТС] |
3 |
tsar925, А если начальная кодировка cp1251 ?
0 |
alex925 2738 / 2341 / 620 Регистрация: 19.03.2012 Сообщений: 8,832 |
||||
21.12.2014, 18:45 |
4 |
|||
Если в твоё приложение приходить строка в cp1251, то просто эту строку декодируешь во внутреннее представление строк (в utf8) и все.
0 |
ivsatel 45 / 39 / 24 Регистрация: 29.11.2013 Сообщений: 139 |
||||
21.12.2014, 19:06 [ТС] |
5 |
|||
tsar925, Что-то делаю не так?
Кстати в браузере кракозябры четко преобразуются при сохранении поста.
0 |
2738 / 2341 / 620 Регистрация: 19.03.2012 Сообщений: 8,832 |
|
21.12.2014, 19:14 |
6 |
Вторая строка неправильная, у тебя за место cp1251 должно быть написано utf8, потому что метод decode принимает значение кодировки в которой закодирована строка сейчас.
1 |
ivsatel 45 / 39 / 24 Регистрация: 29.11.2013 Сообщений: 139 |
||||
21.12.2014, 20:49 [ТС] |
7 |
|||
Получилось вот так:
0 |