Вечно путаюсь в этих кодировках, поэтому решил сделать себе памятку. Покажу на примере.
Итак, кодировка исходного кода задается в первой-второй строке:
#-*-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’\u041c\u0430\u043c\u0430 \u043c\u044b\u043b\u0430 \u0440\u0430\u043c\u0443′
UTF-8: ‘\xd0\x9c\xd0\xb0\xd0\xbc\xd0\xb0 \xd0\xbc\xd1\x8b\xd0\xbb\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xbc\xd1\x83’
нормальный вид: ‘Мама мыла раму’
Итак, чтобы у нас не было проблем с кодировками, нам достаточно сделать вот так:
raw_data = urllib.urlopen(«bla bla bla»).read().decode(‘WINDOWS-1251’).enco
de(‘UTF-8’)
И теперь наша запарсеная страница в той же кодировке что и исходник программы, и можно смело использовать кириллицу в регулярках, или в других ваших решениях. Конечно это не единственное решение, но в моем случае самое простое и удобное.
У сайта есть:
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
При запуске кода:
response = requests.get('url', headers = {'UserAgent': UserAgent().Chrome})
print(response.text)
Ответ примерно такой:
<font face="Verdana"><font color="#FFFFCC" size="2">Óïðàæíåíèå XXVI/6: ãðóïïèðîâàíèå</font><br>
Если это сохранить при помощи:
with open('1.html', 'w', encoding='utf-8') as file:
file.write(response.text)
То ничего не изменится.
Если просто, то надо сделать текст читаемым, чтоб при просмотре в bs4 и последующем сохранении в файлы можно было видеть текст в utf-8.
Как быть?
-
Вопрос задан
-
7967 просмотров
Оказалось что библиотека Requests кодирует данные в кодировку Latin-1(ISO-8859-1), сайт же отправляет данные с кодировкой windows-1251. Получалось что библиотека перекодировала данные сайта в другую кодировку.
Решил так:
sourse = requests.get('url')
sourse.encoding='windows-1251' # Теперь requests отдаёт данные в кодировке windows-1251 которая уже нормально читается
В принципе можно остаться на этой кодировке если при записи в файл указать encoding=’utf-8′
Ну если прям сильно хочется перекодировать в utf-8, можно раскодировать текст в utf-8 а потом закодировать в него
# if text is windows-1251
text = '123 asdasd 55f'
text = encode('utf-8').decode('utf-8')
Пригласить эксперта
Войдите, чтобы написать ответ
-
Показать ещё
Загружается…
Минуточку внимания
Уведомления
- Начало
- » Python для новичков
- » Как файл в кодировке cp1251 сохранить в utf-8
#1 Ноя. 21, 2008 22:35:02
Как файл в кодировке cp1251 сохранить в utf-8
Проблема в том, что я из интернета загружаю страничку. Она в cp1251. Так как обрабатывать её в этой кодировке довольно проблематично, то её нужно перекодировать в utf-8. Вопрос: как?
Офлайн
- Пожаловаться
#2 Ноя. 21, 2008 23:12:02
Как файл в кодировке cp1251 сохранить в utf-8
Сохранить в утф или обрабатывать в программе в юникоде?
Офлайн
- Пожаловаться
#3 Ноя. 21, 2008 23:23:07
Как файл в кодировке cp1251 сохранить в utf-8
text_in_cp1251 = open('cp1251.html', 'rb').read()
text_in_unicode = text_in_cp1251.decode('cp1251')
text_in_utf8 = text_in_unicode.encode('utf8')
open('utf8.html', 'wb').write(text_in_utf8)
RTFM, в конце концов же.
Ведь это так просто.
..bw
Отредактировано (Ноя. 22, 2008 00:18:36)
Офлайн
- Пожаловаться
#4 Ноя. 22, 2008 02:57:42
Как файл в кодировке cp1251 сохранить в utf-8
bw
Ведь это так просто.
На то я и чайник!
Офлайн
- Пожаловаться
#5 Ноя. 22, 2008 03:30:53
Как файл в кодировке cp1251 сохранить в utf-8
Alexsss, на то вы чайник, чтобы учиться, а не чтобы перекладывать всю работу на других.
Офлайн
- Пожаловаться
#6 Ноя. 22, 2008 03:54:18
Как файл в кодировке cp1251 сохранить в utf-8
Или более быстрый и менее затратный для памяти вариант, пригодный для очень больших файлов. Главное, чтобы переносы строк были…
f = file("utf8.html", "wb")
for line in file("cp1251.html", "rb"):
f.write(line.decode('cp1251').encode('utf8'))
P.S. Насколько я помню, open теперь использовать некошерно.
Офлайн
- Пожаловаться
#8 Ноя. 23, 2008 02:41:48
Как файл в кодировке cp1251 сохранить в utf-8
> то можно использовать текстовой редактор
А еще можно использовать iconv :-).
..bw
Отредактировано (Ноя. 23, 2008 02:42:30)
Офлайн
- Пожаловаться
#9 Янв. 14, 2011 17:21:55
Как файл в кодировке cp1251 сохранить в utf-8
ZZZ
Или более быстрый и менее затратный для памяти вариант, пригодный для очень больших файлов. Главное, чтобы переносы строк были…f = file("utf8.html", "wb")
for line in file("cp1251.html", "rb"):
f.write(line.decode('cp1251').encode('utf8'))P.S. Насколько я помню, open теперь использовать некошерно.
Вообще-то, в последней строке с точность наоборот:
f = file("utf8.html", "wb")
for line in file("cp1251.html", "rb"):
f.write(line.decode('utf8').encode('cp1251'))
По крайней мере, в PortablePython 2.5
Офлайн
- Пожаловаться
#10 Янв. 14, 2011 17:30:32
Как файл в кодировке cp1251 сохранить в utf-8
-=<fantom>=-, зачем тему поднимать двухлетней давности?
Офлайн
- Пожаловаться
- Начало
- » Python для новичков
- » Как файл в кодировке cp1251 сохранить в utf-8
Сегодня мы нырнем в пучину одной из самых «волосатых» тем в программировании — кодировку символов. Если вы когда-нибудь видели в консоли надпись Привет!
вместо «Привет!», значит, вы уже знакомы с тем, как кодировки могут превратить ваш код в тарабарщину. Но не паникуйте! Мы разберемся, как Python работает с символами, почему ваш текст иногда выглядит как послание инопланетян, и как этого избежать. Вперед, в мир байтов, Unicode и магии преобразований!
Что такое кодировка?
Представьте, что компьютер — это иностранец, который понимает только цифры. Когда вы пишете букву «А», он видит не символ, а число. Кодировка — это словарь, который говорит: «Эй, машина, число 65 — это буква ‘A’, а число 1040 — это русская ‘А'». Без кодировок компьютеры бы просто путали кириллицу с эмодзи 😱.
ASCII — дедушка всех кодировок
В начале времен (в 1960-х) появилась кодировка ASCII. Она использовала 7 бит и могла записать 128 символов: латиницу, цифры и знаки препинания. Но тут возникла проблема: как впихнуть в 128 символов кириллицу, иероглифы или смайлы? Ответ: никак. ASCII — как маленькая квартира: места хватит только для базового набора.
Unicode — спаситель человечества
Чтобы все языки мира уместились в одном «алфавите», создали Unicode — мегасловарь, где каждому символу присвоен уникальный номер (например, U+0410
для «А»). Но как хранить эти номера в памяти? Тут на сцену выходят кодировки вроде UTF-8, UTF-16 и других. Они решают, как превратить номер символа в байты (и обратно).
Python и кодировки
В Python 3 есть два типа данных для работы с текстом и байтами:
-
str
— это строки в Unicode. Они как идеальный переводчик: понимают все языки. -
bytes
— это «сырые» байты, последовательность чисел от 0 до 255. Они как коробка с пазлами: пока не соберешь, не поймешь, что внутри.
Пример:
text = "Привет, 世界!" # Это строка (str), Unicode
binary_data = text.encode('utf-8') # А это байты (bytes): b'\xd0\x9f\xd1\x80...'
Если попытаться вывести binary_data
без декодирования, получите нечто вроде b'\xd0\x9f...'
— это байты в шестнадцатеричном формате. Чтобы превратить их обратно в текст, нужно правильно выбрать кодировку (как ключ от замка).
UTF-8 и Другие кодировки
UTF-8 — это король современных кодировок. Почему?
-
Он обратно совместим с ASCII: старые тексты работают без проблем.
-
Экономит место: английский текст занимает столько же байт, сколько в ASCII.
-
Поддерживает все символы Unicode, включая эмодзи 🦄.
Другие кодировки:
-
UTF-16 и UTF-32 — используют 2 или 4 байта на символ. Мощно, но расточительно.
-
Windows-1251 (кириллица) и ISO-8859-1 (Европа) — локальные герои, но за пределами своей зоны бесполезны.
-
KOI8-R — ретро-кодировка для русского языка, как виниловая пластинка: редко, но атмосферно.
Проблема: Если открыть файл в неправильной кодировке, текст превратится в кракозябры. Например, русский текст в Windows-1251
, прочитанный как ISO-8859-1
, станет чем-то вроде «РџСЂРёРІРµС‚!».
Таблица с популярными кодировками, их описанием и примерами использования:
Кодировка | Описание | Пример использования |
---|---|---|
ASCII | 7-битная кодировка, поддерживает только английский алфавит, цифры и символы. | A → 65 , a → 97 |
UTF-8 | Универсальная кодировка, поддерживает все символы Unicode. Экономит место для ASCII. | A → 65 , Я → D0 AF , 😊 → F0 9F 98 8A |
UTF-16 | Использует 2 или 4 байта на символ. Подходит для текстов с большим количеством символов за пределами ASCII. | A → 00 41 , Я → 04 2F , 😊 → D8 3D DE 0A |
UTF-32 | Использует 4 байта на символ. Простая, но расточительная кодировка. | A → 00 00 00 41 , Я → 00 00 04 2F |
Windows-1251 | Кодировка для кириллицы, используется в Windows. | А → C0 , Я → DF |
ISO-8859-1 | Кодировка для западноевропейских языков (латиница). | A → 41 , é → E9 |
KOI8-R | Кодировка для русского языка, популярная в Unix-системах. | А → E1 , Я → D1 |
CP866 | Кодировка для кириллицы, использовалась в DOS. | А → 80 , Я → AF |
Shift_JIS | Кодировка для японского языка. | あ → 82 A0 , ア → 83 41 |
GB2312 | Кодировка для китайского языка (упрощенные иероглифы). | 中 → D6 D0 , 文 → CE C4 |
EBCDIC | Кодировка, используемая в мейнфреймах IBM. | A → C1 , 0 → F0 |
Пояснения к таблице:
-
ASCII — базовая кодировка, но она не поддерживает кириллицу, иероглифы или эмодзи.
-
UTF-8 — самая популярная кодировка в современном мире. Она поддерживает все символы Unicode и экономит место для текстов на английском.
-
UTF-16 и UTF-32 — используются реже, но полезны для специфических задач, где важна простота обработки.
-
Windows-1251 и KOI8-R — локальные кодировки для русского языка. Если открыть файл в неправильной кодировке, текст превратится в кракозябры.
-
Shift_JIS и GB2312 — кодировки для азиатских языков. Они поддерживают тысячи иероглифов.
-
EBCDIC — устаревшая кодировка, но до сих пор используется в некоторых банковских системах.
Примеры использования:
-
UTF-8:
text = "Привет, мир! 😊" binary = text.encode('utf-8') # b'\xd0\x9f\xd1\x80...' decoded = binary.decode('utf-8') # "Привет, мир! 😊"
-
Windows-1251:
text = "Привет!" binary = text.encode('windows-1251') # b'\xcf\xf0\xe8\xe2\xe5\xf2!' decoded = binary.decode('windows-1251') # "Привет!"
-
KOI8-R:
text = "Привет!" binary = text.encode('koi8-r') # b'\xf0\xd2\xc9\xd7\xc5\xd4!' decoded = binary.decode('koi8-r') # "Привет!"
Важно:
-
Всегда указывайте кодировку при работе с файлами или сетевыми запросами.
-
Если вы не уверены в кодировке, попробуйте угадать её с помощью библиотек, например
chardet
:import chardet data = b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82!' result = chardet.detect(data) print(result) # {'encoding': 'utf-8', 'confidence': 0.99}
Байты и строки
Представьте: вы получили сообщение в байтах — b'\xd0\x9f\xd1\x80\xd0\xb8...'
. Как понять, что это?
-
Если это русский текст, попробуйте декодировать через
utf-8
:binary_data.decode('utf-8') # "Привет!"
-
Если декодировать через
latin-1
, получите «ÐŸÑ€Ð¸…» — типичные кракозябры.
Важно: Байты — это не текст! Это как коробка с зашифрованным посланием. Без правильного «ключа» (кодировки) вы его не прочитаете.
Совет: Всегда явно указывайте кодировку при работе с файлами:
# Открываем файл с указанием кодировки
with open('secret.txt', 'r', encoding='utf-8') as file:
text = file.read()
Если пропустить encoding
, Python использует системную кодировку по умолчанию. На Windows это часто cp1251
, и тогда ваш файл в utf-8
превратится в «иероглифы».
Шестнадцатеричные Escape-символы
Иногда Python показывает символы в виде \x41
(для «A») или \u0410
(для «А»). Это шестнадцатеричное представление символов. Например:
-
\x41
— байт0x41
(65 в десятичной) → символ «A». -
\u0410
— Unicode-символ с кодомU+0410
→ русская «А».
Пример «магии»:
text = "\u0031\u0432\u0430\u043d" # "1ван"
Это удобно, если нужно вставить символ, которого нет на клавиатуре.
Кодировки в строках
В Python есть префиксы для строк, которые меняют их поведение:
-
b''
— строка байтов:b'hello'
. -
u''
— строка Unicode (в Python 3 это по умолчанию). -
r''
— «сырая» строка (игнорирует экранирование):r'C:\Users\Хакер'
.
Совет: Префикс r
спасает, когда нужно использовать обратные слеши без экранирования (например, в регулярных выражениях или путях файлов).
Ошибки кодировки
Когда Python не может преобразовать байты в строку (или наоборот), он выбрасывает ошибку. Самые частые:
-
UnicodeEncodeError
— попытка записать символ, которого нет в целевой кодировке.
Например, записать русскую «Я» в ASCII (он её не знает). -
UnicodeDecodeError
— попытка прочитать байты в неправильной кодировке.
Например, прочитатьutf-8
какcp1251
.
Решение: Используйте параметр errors
:
-
ignore
— пропустить недопустимые символы. -
replace
— заменить их на?
(для декодирования) или\ufffd
(для кодирования). -
xmlcharrefreplace
— заменить на XML-сущности (например,А
для «А»).
Пример:
text = "Привет, 🐍"
binary = text.encode('ascii', errors='replace') # b'??????, ?'
Кодировки и Веб
Если вы отправляете данные на сервер или в браузер без указания кодировки, возможны два исхода:
-
Все работает (если повезет).
-
Пользователи видят абракадабру и шлют вам гневные письма.
HTTP-заголовки и HTML-теги должны явно указывать кодировку:
<meta charset="UTF-8">
Иначе браузер попытается угадать её, что может привести к «сюрпризам». Например, кириллица может отобразиться как РґРІР°
вместо «два».
Забавные факты о кодировках
-
Эмодзи в Unicode — это тоже символы! 🎉 Смайлик «😂» имеет код
U+1F602
. -
Самый редкий символ —
U+1F47D
(👽). Привет, инопланетяне! -
Споры о пробеле: В Unicode есть пробелы разной ширины (например,
U+2002
— средний пробел). Дизайнеры это оценят. -
Кодировка EBCDIC, использовавшаяся в мейнфреймах IBM, до сих пор жива в некоторых банковских системах. Это как динозавр в IT-музее.
Философия кодировок
Кодировки — это мосты между людьми и машинами. Они позволяют:
-
Сохранять знания на всех языках.
-
Общаться без границ (даже если ваш друг говорит на китайском, а вы — на суахили).
-
Создавать программы, которые понимают весь мир.
Помните: Неправильная кодировка — как неправильный переводчик на переговорах. Может выйти конфуз!
Заключение: Кодируй с умом, и будет тебе счастье
Теперь вы знаете, что кодировки — это не страшные монстры, а инструменты. Главное — всегда явно указывать, с чем работаете. Используйте UTF-8, проверяйте кодировки файлов и не доверяйте «автоопределению».
И если вы вдруг увидите в консоли Так здорово!
, не спешите винить Python. Возможно, вы просто забыли сказать ему: «Эй, это же UTF-8!». Удачи в мире байтов и символов! 😎
#!/usr/bin/python
# -*- coding: utf-8 -*-
import chardet
import Tkinter
from Tkinter import Label
from Tkinter import Tk
from Tkinter import X
from tkFileDialog import askopenfilename
import os
def open_file():
try:
filename = askopenfilename()
f = open(filename, ‘r’).read()
except UnicodeDecodeError:
print «can’t open this file»
else:
try:
encoding = chardet.detect(f)
print encoding
except UnicodeDecodeError:
print(‘can\’t detect encoding’)
else:
if encoding[‘encoding’] == ‘ascii’:
print ‘Encoding is: ascii’
elif encoding[‘encoding’] == ‘windows-1251’:
res.configure(text=«Encoding is: windows-1251», fg=«blue»)
elif encoding[‘encoding’] == ‘utf-8’:
res.configure(text=«Encoding is: utf-8», fg=«blue»)
elif encoding[‘encoding’] == ‘None’:
res.configure(text=«Encoding is: None», fg=«blue»)
else:
res.configure(text=‘Encoding can\’t be detected’, fg=«blue»)
print ‘Encoding can\’t be detected’
def convert_from_windows_1251():
filename = askopenfilename()
try:
f = open(filename, ‘r’).read()
except UnicodeDecodeError:
print «it was not a windows-1251 unicode»
else:
try:
unicode_text = f.decode(‘cp1251’)
except UnicodeDecodeError:
print(‘unicode error, trying different encoding’)
else:
abs_path = os.path.join(os.path.dirname(__file__), ‘output_from_cp1251_to_utf8.txt’)
text_in_1251 = unicode_text.encode(‘utf-8’)
f = open(abs_path, ‘w’)
f.write(text_in_1251)
def convert_from_utf8_to_windows_1251():
filename = askopenfilename()
try:
f = open(filename, ‘r’).read()
except UnicodeDecodeError:
print «it was not a utf-8 unicode»
else:
try:
unicode_text = f.decode(‘utf-8’)
except UnicodeDecodeError:
print(‘unicode error, trying different encoding’)
else:
abs_path = os.path.join(os.path.dirname(__file__), ‘output_from_utf8_to_cp1251.txt’)
text_in_1251 = unicode_text.encode(‘cp1251’)
f = open(abs_path, ‘w’)
f.write(text_in_1251)
root = Tk()
root.title(‘UTF-8 Converter’)
root.geometry(‘250×250+500+300’)
root.config(background=«#FFFFFF»)
button = Tkinter.Button(root, text=«Check encoding», width=25, bg=«#FFFFFF», command=open_file)
button.pack(fill=X, padx=10, pady=20)
res = Label(root, bg=«#FFFFFF»)
res.pack()
button1 = Tkinter.Button(root, text=«Convert from windows-1251 to utf-8», width=25, bg=«#FFFFFF»,
command=convert_from_windows_1251)
button1.pack(fill=X, padx=10, pady=15)
button1 = Tkinter.Button(root, text=«Convert from utf-8 to windows-1251», width=25, bg=«#FFFFFF»,
command=convert_from_utf8_to_windows_1251)
button1.pack(fill=X, padx=10, pady=15)
exit_button = Tkinter.Button(root, text=‘Quit’, command=root.destroy, bg=«#FFFFFF»)
exit_button.pack(side=‘bottom’)
root.mainloop()