Кодировка windows 1251 python

Вечно путаюсь в этих кодировках, поэтому решил сделать себе памятку. Покажу на примере.

Итак, кодировка исходного кода задается в первой-второй строке:

#-*-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’).encode(‘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 есть два типа данных для работы с текстом и байтами:

  1. str — это строки в Unicode. Они как идеальный переводчик: понимают все языки.

  2. 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-битная кодировка, поддерживает только английский алфавит, цифры и символы. A65, a97
UTF-8 Универсальная кодировка, поддерживает все символы Unicode. Экономит место для ASCII. A65, ЯD0 AF, 😊F0 9F 98 8A
UTF-16 Использует 2 или 4 байта на символ. Подходит для текстов с большим количеством символов за пределами ASCII. A00 41, Я04 2F, 😊D8 3D DE 0A
UTF-32 Использует 4 байта на символ. Простая, но расточительная кодировка. A00 00 00 41, Я00 00 04 2F
Windows-1251 Кодировка для кириллицы, используется в Windows. АC0, ЯDF
ISO-8859-1 Кодировка для западноевропейских языков (латиница). A41, éE9
KOI8-R Кодировка для русского языка, популярная в Unix-системах. АE1, ЯD1
CP866 Кодировка для кириллицы, использовалась в DOS. А80, ЯAF
Shift_JIS Кодировка для японского языка. 82 A0, 83 41
GB2312 Кодировка для китайского языка (упрощенные иероглифы). D6 D0, CE C4
EBCDIC Кодировка, используемая в мейнфреймах IBM. AC1, 0F0

Пояснения к таблице:

  1. ASCII — базовая кодировка, но она не поддерживает кириллицу, иероглифы или эмодзи.

  2. UTF-8 — самая популярная кодировка в современном мире. Она поддерживает все символы Unicode и экономит место для текстов на английском.

  3. UTF-16 и UTF-32 — используются реже, но полезны для специфических задач, где важна простота обработки.

  4. Windows-1251 и KOI8-R — локальные кодировки для русского языка. Если открыть файл в неправильной кодировке, текст превратится в кракозябры.

  5. Shift_JIS и GB2312 — кодировки для азиатских языков. Они поддерживают тысячи иероглифов.

  6. EBCDIC — устаревшая кодировка, но до сих пор используется в некоторых банковских системах.


Примеры использования:

  1. UTF-8:

    text = "Привет, мир! 😊"
    binary = text.encode('utf-8')  # b'\xd0\x9f\xd1\x80...'
    decoded = binary.decode('utf-8')  # "Привет, мир! 😊"
  2. Windows-1251:

    text = "Привет!"
    binary = text.encode('windows-1251')  # b'\xcf\xf0\xe8\xe2\xe5\xf2!'
    decoded = binary.decode('windows-1251')  # "Привет!"
  3. 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 не может преобразовать байты в строку (или наоборот), он выбрасывает ошибку. Самые частые:

  1. UnicodeEncodeError — попытка записать символ, которого нет в целевой кодировке.
    Например, записать русскую «Я» в ASCII (он её не знает).

  2. UnicodeDecodeError — попытка прочитать байты в неправильной кодировке.
    Например, прочитать utf-8 как cp1251.

Решение: Используйте параметр errors:

  • ignore — пропустить недопустимые символы.

  • replace — заменить их на ? (для декодирования) или \ufffd (для кодирования).

  • xmlcharrefreplace — заменить на XML-сущности (например, &#1040; для «А»).

Пример:

text = "Привет, 🐍"
binary = text.encode('ascii', errors='replace')  # b'??????, ?'

Кодировки и Веб

Если вы отправляете данные на сервер или в браузер без указания кодировки, возможны два исхода:

  1. Все работает (если повезет).

  2. Пользователи видят абракадабру и шлют вам гневные письма.

HTTP-заголовки и HTML-теги должны явно указывать кодировку:

<meta charset="UTF-8">

Иначе браузер попытается угадать её, что может привести к «сюрпризам». Например, кириллица может отобразиться как РґРІР° вместо «два».


Забавные факты о кодировках

  • Эмодзи в Unicode — это тоже символы! 🎉 Смайлик «😂» имеет код U+1F602.

  • Самый редкий символU+1F47D (👽). Привет, инопланетяне!

  • Споры о пробеле: В Unicode есть пробелы разной ширины (например, U+2002 — средний пробел). Дизайнеры это оценят.

  • Кодировка EBCDIC, использовавшаяся в мейнфреймах IBM, до сих пор жива в некоторых банковских системах. Это как динозавр в IT-музее.


Философия кодировок

Кодировки — это мосты между людьми и машинами. Они позволяют:

  • Сохранять знания на всех языках.

  • Общаться без границ (даже если ваш друг говорит на китайском, а вы — на суахили).

  • Создавать программы, которые понимают весь мир.

Помните: Неправильная кодировка — как неправильный переводчик на переговорах. Может выйти конфуз!


Заключение: Кодируй с умом, и будет тебе счастье

Теперь вы знаете, что кодировки — это не страшные монстры, а инструменты. Главное — всегда явно указывать, с чем работаете. Используйте UTF-8, проверяйте кодировки файлов и не доверяйте «автоопределению».

И если вы вдруг увидите в консоли Так здорово!, не спешите винить Python. Возможно, вы просто забыли сказать ему: «Эй, это же UTF-8!». Удачи в мире байтов и символов! 😎

  • Home
  • /
  • Windows-1251

  • /
  • Windows-1251 Encoding : Python

Welcome to our comprehensive guide on Windows-1251 encoding in Python! If you’re working with Cyrillic text or engaging with data from Eastern European languages, understanding Windows-1251 encoding is essential. In this article, we’ll explore what Windows-1251 encoding is, its importance in text processing, and how to effectively use it in Python. You’ll learn practical tips for encoding and decoding strings, handling data files, and troubleshooting common issues. Whether you’re a beginner or an experienced developer, this guide will equip you with the knowledge you need to manage text encoding seamlessly in your Python projects.

Introduction to Windows-1251

Windows-1251 is a character encoding system designed to support languages that use the Cyrillic alphabet, such as Russian, Bulgarian, and Serbian. Developed by Microsoft, it is widely used in various applications and systems. Windows-1251 is an 8-bit encoding scheme that can represent 256 different characters, including control characters, punctuation marks, and alphanumeric symbols. Understanding Windows-1251 encoding is essential for developers working with text data in these languages, especially when dealing with legacy systems or file formats that do not support Unicode.

Encoding text using Windows-1251 in Python is straightforward, thanks to the built-in encode() method. This method allows you to convert a string into bytes using the specified character encoding. Here’s how you can encode a string in Windows-1251:

# Sample string in Russian
text = "Привет, мир!"  # "Hello, World!" in Russian
# Encoding the string using Windows-1251
encoded_text = text.encode('windows-1251')
# Displaying the encoded byte string
print(encoded_text)  # Output: b'\xcf\xf0\xe8\xe2\xe5\xf2, \xec\xb8\xf0!'

In this example, the string «Привет, мир!» is encoded into a byte string using Windows-1251, which is suitable for storage or transmission in systems that require this encoding.

Decoding with Windows-1251 in Python

Decoding Windows-1251 encoded data back into a readable string format can also be accomplished using the decode() method in Python. This method converts bytes back into a string using the specified character encoding. Here’s an example:

# Sample byte string encoded in Windows-1251
encoded_text = b'\xcf\xf0\xe8\xe2\xe5\xf2, \xec\xb8\xf0!'
# Decoding the byte string back to a regular string
decoded_text = encoded_text.decode('windows-1251')
# Displaying the decoded string
print(decoded_text)  # Output: Привет, мир!

This example demonstrates how to reverse the encoding process, allowing you to retrieve the original string from its byte representation.

Advantages and Disadvantages of Windows-1251

Advantages

  1. Simplicity: Windows-1251 is straightforward and easy to implement, especially for applications targeting Cyrillic languages.
  2. Legacy Support: Many older systems and applications still use Windows-1251, making it essential for compatibility with legacy data.
  3. Efficiency: Being an 8-bit encoding, it can be more efficient in terms of storage when dealing with Cyrillic text compared to multi-byte encodings like UTF-8.

Disadvantages

  1. Limited Character Set: Windows-1251 only supports Cyrillic characters, making it unsuitable for multilingual applications that require broader character support.
  2. Lack of Standardization: Unlike Unicode, which is a universal standard, Windows-1251 is proprietary and may not be recognized across all platforms.
  3. Potential Data Loss: When converting between Windows-1251 and other encodings, there is a risk of data loss or corruption for characters not supported by Windows-1251.

Key Applications of Windows-1251

Windows-1251 is primarily used in applications that need to display or process text in Cyrillic scripts. Key applications include:

  • Text Editors: Many text editors support Windows-1251 for editing documents in Russian and other Cyrillic languages.
  • Web Development: Websites targeting Russian-speaking audiences may use Windows-1251 encoding in their HTML pages and server responses.
  • Databases: Legacy database systems often rely on Windows-1251 encoding for storing and retrieving text data in Cyrillic languages.

Popular Frameworks and Tools for Windows-1251

Several programming frameworks and tools support Windows-1251 encoding, making it easier for developers to work with Cyrillic text:

  • Flask: A lightweight web framework for Python that allows you to specify character encoding in HTTP responses.
  • Django: A high-level Python web framework that supports various character encodings, including Windows-1251, for internationalization.
  • Pandas: A powerful data manipulation library in Python that can read and write CSV files encoded in Windows-1251.

By utilizing these frameworks and tools, developers can seamlessly integrate Windows-1251 encoding into their applications, ensuring proper handling of Cyrillic text.

Contents

  • Lesson Goals
  • What Is Transliteration and for Whom Is It Useful?
  • Converting a Webpage to Unicode
  • Unicode Transliteration Dictionary
  • Transliterated List of Names

Lesson Goals

This lesson shows how to use Python to transliterate automatically a
list of words from a language with a non-Latin alphabet to a
standardized format using the American Standard Code for Information
Interchange (ASCII) characters. It builds on readers’ understanding
of Python from the lessons “Viewing HTML Files,” “Working with Web
Pages,” “From HTML to List of Words (part 1)” and “Intro to
Beautiful Soup.” At the end of the lesson, we will use the
transliteration dictionary to convert the names from a database of the
Russian organization Memorial from Cyrillic into Latin
characters. Although the example uses Cyrillic characters, the
technique can be reproduced with other alphabets using Unicode.

What Is Transliteration and for Whom Is It Useful?

Transliteration is something that most people do every day, knowingly or
not. Many English speakers would have trouble recognizing the name
Владимир Путин but know that Vladimir Putin is Russia’s current
president. Transliteration is especially useful with names, because a
standardized transliterated name is often the same as a translated name.
(Exceptions are when someone’s name is translated in a non-uniform way.
Leon Trotsky’s Russian name would be transliterated in a standardized
form as Lev Trotskii.)

But transliteration has other uses too, especially for scholars. In many
fields, the publishing convention is to transliterate any evidence used
in the original. Moreover, citations from scholarly works need to be
transliterated carefully so that readers can find and verify evidence
used in texts. Finally, transliteration can be more practical for
authors who can type more fluently with Latin letters than in the native
alphabet of a language that does not use Latin characters.

This lesson will be particularly useful for research in fields that use
a standardized transliteration format, such as Russian history field,
where the convention is to use a simplified version of the American
Library Association-Library of Congress (ALA-LC) transliteration
table. (All tables currently available can be accessed here.)
Researchers dealing with large databases of names can benefit
considerably. However, this lesson will also allow practice with
Unicode, character translation and using the parser Beautiful Soup in
Python.

Converting a Webpage to Unicode

The goal of this lesson is to take a list of names from a Russian
database and convert them from Cyrillic into ASCII characters. The page
we will use is from the site of the Russian human rights organization
Memorial. During Glasnost professional and amateur historians in the
Soviet Union gained the ability to conduct research on previously taboo
subjects, such as repression under Stalin. Banding together, they
founded Memorial to collect and publicize their findings. Today, the
NGO conducts research on a range of civil rights abuses in Russia, but
collecting data about the victims of Stalinism remains one of its main
functions. On the Memorial website researchers can find a database with
some three million entries of people who were arrested or executed by
Stalin’s regime. It is an important resource on a dark topic. However,
because the database has many, many names, it lends itself nicely to
automated transliteration. This lesson will use just the first page of
the database, found here, but using the lesson on “Automated
Downloading with Wget,” it would be possible to go through the entire
database as fast as your computer would allow.

We need to start by modifying the process found in the lesson “Working
with Web Pages.” There we learned how to open and copy the HTML from
a web page in Python. But what if we want to open a page in a language
that does not use Latin characters? Python can do this but we need to
tell it how to read these letters using a codec, a library of codes that
allows Python to represent non-ASCII characters. Working with web pages
makes this easy because almost all web pages specify what kind of
encoding they use, in the page’s headers. In Python, opening a web page
does not just give you the HTML, but it creates an object with several
useful characteristics. One is that we can access the headers by calling
the header() method. This method returns something a lot like a Python
dictionary with information that is important to web programmers. For
our purposes, what is important is that the encoding is stored under the
‘content-type’ key.

#transliterator.py
from urllib.request import urlopen

page = urlopen('http://lists.memo.ru/d1/f1.htm')

#what is the encoding?
print(page.headers['content-type'])

Under the ‘content-type’ key we find this information:

text/html; charset=windows-1251

The ‘content-type’ is telling us that the file stored at the url we
accessed is in HTML and that its encoding (after ‘charset=’, meaning
character set) is ‘windows-1251′, a common encoding for Cyrillic
characters. You can visit the webpage and view the Page Source and see
for yourself that the first line does in fact contain a ‘content-type’
variable with the value text/html; charset=windows-1251. It would not be
so hard to work with the ‘windows-1251′ encoding. However,
‘windows-1251′ is specifically for Cyrillic and will not handle all
languages. For the sake of learning a standard method, what we want is
Unicode, a coding set that handles not just Cyrillic but characters and
symbols from virtually any language. (For more on Unicode, see the What
is Unicode page.) Converting into Unicode gives us the potential to
create a transliteration table that could cover multiple languages and
special characters in a way that region-specific character sets do not
allow.

How do you convert the characters to Unicode? First, Python needs to
know the original encoding of the source, ‘windows-1251.’ We could just
assign ‘windows-1251’ to a variable by typing it manually but the
encoding may not always be ‘windows-1251.’ There are other character
sets for Cyrillic, not to mention other languages. Let’s find a way to
make the process more automatic for those cases. It helps that the
encoding is the very last part of the string, so we can isolate it from
everything that came before in the string. By using the .split() method,
the string containing whatever encoding it is can be assigned to a
variable. The .split(separator) method in Python returns a list of
sections in the string that are split by some user-defined separator.
Assigning no separator to .split() separates a string at the spaces.
Another use of the .split() method is to separate by commas, which can
help to work with comma separated value (csv) files. In this case,
though, by splitting the ‘content-type’ string at ‘charset=’, we get a
list with two strings where the second will be the character set.

encoding = page.headers['content-type'].split('charset=')[1]

The encoding is assigned to the variable called ‘encoding’. You can
check to see if this worked by printing the ‘encoding’ variable. Now we
can tell Python how to read the page as Unicode. Using the
str(object [, encoding]) method turns a text encoded in a specific encoding
into a generic Unicode string. A Unicode string cannot only contain ASCII
characters, but also
special characters. If the original text is in a non-ASCII character set,
like here with ‘windows-1251’, we have to use the optional encoding
parameter.

#read the HTML as a string into a variable
content = page.read()

# the unicode method tries to use ASCII so we need to tell it the encoding
content = str(content, encoding)
content[200:300]
'"list-right">\r\n<li><p class="name"><a name="n1"></a>А-Аку Туликович </p><p class="cont">\r\nРодился\xa0в '

As you can see, the Cyrillic characters are mixed with the ASCII characters
of the HTML code. But typing these can be cumbersome without a corresponding
keyboard layout. Alternatively, the Unicode characters can be typed using
special codes that represent the characters using their Unicode number.
You can see the text as represented by Unicode numbers using the special ‘unicode-escape’ encoding:

# print string using unicode escape sequences
print(content[200:300].encode('unicode-escape'))
b'"list-right">\\r\\n<li><p class="name"><a name="n1"></a>\\u0410-\\u0410\\u043a\\u0443 \\u0422\\u0443\\u043b\\u0438\\u043a\\u043e\\u0432\\u0438\\u0447 </p><p class="cont">\\r\\n\\u0420\\u043e\\u0434\\u0438\\u043b\\u0441\\u044f\\xa0\\u0432 '

All the
‘\u0420’-type marks are Unicode and Python knows that they code to
Cyrillic characters. The backslash is called an ‘escape character
and allows Python to do things like use special characters in Unicode or
signify a line break (‘\n’) in a document. Each counts as just one
character. Now we can create a Python dictionary that will act as the
transliteration table.

Unicode Transliteration Dictionary

A dictionary is an unordered collection of key-object pairs. What this
means is that under each key, the dictionary stores some number or
string or other object – even another dictionary. (See also the lesson
“Counting Frequencies.”) A dictionary has the following syntax:

my_dictionary = {'Vladimir': 'Putin', 'Boris': 'Yeltsin'}
print(my_dictionary['Vladimir'])

> Putin

How can we turn this into a transliteration table? Just make each
Unicode character a key in the dictionary. Its value will be whatever
character(s) it transliterates to. The table for Romanization of Russian
is available from the Library of Congress. This table needs to be
simplified slightly. The ALA-LC suggests using characters with umlauts
or ligatures to represent Cyrillic letters but those characters are no
more ASCII than Cyrillic characters. So instead no umlauts or ligatures
will be used.

Each Cyrillic letter has a different Unicode value. It would take time
to find each one of them but fortunately Wikipedia has a table. If
the script were very rare, we could find it at the Unicode website.

We just need to combine the transliteration table with the Unicode
table. The Unicode value for the Russian letter “Ж” is 0416 and it
transliterates to the Latin characters “Zh.” Python needs more than just
the Unicode identifier. It also needs to know to look out for a Unicode
character. Therefore all the Unicode characters used in the dictionary
should be in the format '\uXXXX'. In this case, the letter Ж is
'\u0416'. We can create a transliteration dictionary and assign ‘Zh’
as the value for the key '\u0416' in it.

cyrillic_translit = { '\u0416': 'Zh'}

As it turns out, lowercase Cyrillic letters in Unicode have the same
value as their uppercase counterparts except the value of the second
number is two greater. Thus, ‘ж’ codes to 0436. Now that we have a
transliteration dictionary created, we just add a dictionary key-value
pair.

cyrillic_translit['\u0436'] = 'zh'

Of course, rather than do each pair one by one, it would probably be
easier to write the dictionary in a Python module or paste it in from a
word processor. The full Cyrillic transliteration dictionary is here:

cyrillic_translit={'\u0410': 'A', '\u0430': 'a',
'\u0411': 'B', '\u0431': 'b',
'\u0412': 'V', '\u0432': 'v',
'\u0413': 'G', '\u0433': 'g',
'\u0414': 'D', '\u0434': 'd',
'\u0415': 'E', '\u0435': 'e',
'\u0416': 'Zh', '\u0436': 'zh',
'\u0417': 'Z', '\u0437': 'z',
'\u0418': 'I', '\u0438': 'i',
'\u0419': 'I', '\u0439': 'i',
'\u041a': 'K', '\u043a': 'k',
'\u041b': 'L', '\u043b': 'l',
'\u041c': 'M', '\u043c': 'm',
'\u041d': 'N', '\u043d': 'n',
'\u041e': 'O', '\u043e': 'o',
'\u041f': 'P', '\u043f': 'p',
'\u0420': 'R', '\u0440': 'r',
'\u0421': 'S', '\u0441': 's',
'\u0422': 'T', '\u0442': 't',
'\u0423': 'U', '\u0443': 'u',
'\u0424': 'F', '\u0444': 'f',
'\u0425': 'Kh', '\u0445': 'kh',
'\u0426': 'Ts', '\u0446': 'ts',
'\u0427': 'Ch', '\u0447': 'ch',
'\u0428': 'Sh', '\u0448': 'sh',
'\u0429': 'Shch', '\u0449': 'shch',
'\u042a': '"', '\u044a': '"',
'\u042b': 'Y', '\u044b': 'y',
'\u042c': "'", '\u044c': "'",
'\u042d': 'E', '\u044d': 'e',
'\u042e': 'Iu', '\u044e': 'iu',
'\u042f': 'Ia', '\u044f': 'ia'}

Now that we have the transliteration dictionary, we can simply loop
through every character in the source page and convert those Unicode
characters in the dictionary. If we turn it into a procedure, then we
can reuse it for other webpages.

def transliterate(word, translit_table):
    converted_word = ''
    for char in word:
        transchar = ''
        if char in translit_table:
            transchar = translit_table[char]
        else:
            transchar = char
        converted_word += transchar
    return converted_word

We can then call this function using the newly created dictionary and
the webpage downloaded earlier.

#we will run it with the cyrillic_translit dictionary and the webpage
converted_content = transliterate(content, cyrillic_translit)
converted_content[200:310]

Here is what we end up with:

'="list-right">\r\n<li><p class="name"><a name="n1"></a>A-Aku Tulikovich </p><p class="cont">\r\nRodilsia\xa0v 1913 g.'

Still not perfect. Python did not convert the special character ‘\xa0′
that signifies a non-breaking space. But with the transliteration
dictionary, any characters that pop up can just be added to the
dictionary and they will be converted. First we need to find out what
that character is. We could search for it on the Internet or we can just
print it:

#let's find out what u'\xa0' is
print('\xa0')

#it's not nothing but a non-breaking space
#it would be better if our transliteration dictionary could change it into a space

cyrillic_translit['\xa0'] = ' '

With this fix, all the Cyrillic and special characters are gone, making
it much easier to read the file and deal with it. For the last part of
the lesson, we will modify methods used in the lesson “Intro to
Beautiful Soup” to get a list of transliterated names from the
webpage.

Transliterated List of Names

There may be cases where it is best to transliterate the entire file but
if the goal is to transliterate and extract just a part of the data in
the file, it would be best to extract first and transliterate later.
That way Python will only transliterate a small part of the file rather
than having to loop through the whole of the HTML. Speed is not a huge
issue when dealing with a handful of web pages but Memorial’s site has
thousands of pages. The difference between looping through thousands of
whole pages and just looping through a small part of each of those pages
can add up. But, of course, it would have been anti-climactic to have
all the names before the transliteration dictionary and also more
difficult for non-Cyrillic readers to understand the rest of the lesson.
So now we need to find a way to get just the names from the page. Here
is the first bit of HTML from the converted_content string, containing
parts of two database entries:

print(converted_content[200:1000])

This code prints out characters 200 to 1000 of the HTML, which happens
to include the entire first entry and the beginning of the second:

="list-right">
<li><p class="name"><a name="n1"></a>A-Aku Tulikovich </p><p class="cont">
Rodilsia v 1913 g., Kamchatskaia gub., Tigil'skii r-n, stoibishcha Utkholok; koriak-kochevnik;  malogramotnyi; b/p;

<br />Arestovan  12 noiabria 1938 g.
<br />Prigovoren: Koriakskii okrsud 8 aprelia 1939 g., obv.: po st. 58-2-8-9-10-11 UK RSFSR.
<br />Prigovor: 20 let. Opredeleniem Voennoi kollegii VS SSSR ot 17 oktiabria 1939 g. mera snizhena do 10 let.
Reabilitirovan 15 marta 1958 g. Reabilitirovan opredeleniem Voennoi kollegii VS SSSR
</p><p class="author">Istochnik: Baza dannykh o zhertvakh repressii Kamchatskoi obl.</p></li>
<li><p class="name"><a name="n2"></a>Aab Avgust Mikhailovich</p><p class="cont">
Rodilsia v 1899 g., Saratovskaia obl., Grimm s.; nemets;  obrazovanie nachal'noe;

Each entry includes lots of information: name (last, first and
patronymic), date of birth, place of birth, profession, date of arrest,
date of sentencing and so on. If we wanted the detailed information
about each person, we would have to parse the page ourselves and extract
that information using the string manipulation techniques from the
lesson “Manipulating Strings in Python.” However, for just the names
it will be quicker to use the HTML parsing module Beautiful Soup. If you
have not installed Beautiful Soup, see “Installing Python Modules with pip”
and read “Intro to Beautiful Soup” for an overview of how
this tool works. In the transliterator module, we will load Beautiful
Soup and then turn our converted page into a Beautiful Soup object.

#load Beautiful Soup
from bs4 import BeautifulSoup

#convert the page
converted_soup = BeautifulSoup(converted_content)

The lesson “Intro to Beautiful Soup” teaches how to grab sections of
a web page by their tags. But we can also select sections of the page by
attributes, HTML code that modifies elements. Looking at the HTML from
this page, notice that the text of our names are enclosed in the tag
<p class="name">. The class attribute allows the page’s Cascading
Style Sheets (CSS) settings to change the look of all elements that
share the “name” class at once. CSS itself is an important tool for web
designers. For those interested in learning more on this aspect of CSS,
I recommend Code Academy’s interactive lessons in its web
fundamentals track. In mining data from the web, though, attributes like
class give us a pattern to separate out certain values.

What we want is to get the elements where the class attribute’s value is
“name”. When dealing with most types of attributes, Beautiful Soup can
select parts of the page using the same syntax as HTML. The class
attribute makes things a little tricky because Python uses “class” to
define new types of objects. Beautiful Soup gets around this by making
us search for class followed by an underscore: class_="value".
Beautiful Soup objects’ .find_all() method will generate a Python list
of Beautiful Soup objects that match the HTML tags or attributes set as
parameters. The method .get_text() extracts just the text from
Beautiful Soup objects, so
" <p class="name"><a name="n1"></a>A-Aku Tulikovich</p> ".get_text()
will become “A-Aku Tulikovich”. We need to use .get_text() on each
item in the list, then append it to a new list containing just the
names:

#creating the final names list
names = []

#creating the list with .find_all() and looping through it
for entry in converted_soup.find_all(class_="name"):
    names.append(entry.get_text())

To make sure it worked, let’s check the number of names and then see if
they look like we expect:

#check the number of names
len(names)

> 190

#see the first twenty names in the list
names[:20]

> ['A-Aku Tulikovich ', 'Aab Avgust Mikhailovich', 'Aab Avgust Khristianovich', 'Aab Aleksandr Aleksandrovich', "Aab Aleksandr Khrist'ianovich", "Aab Al'bert Viktorovich", "Aab Al'brekht Aleksandrovich", 'Aab Amaliia Andreevna', 'Aab Amaliia Ivanovna', 'Aab Angelina Andreevna', 'Aab Andrei Andreevich', 'Aab Andrei Filippovich', 'Aab Arvid Karlovich', "Aab Arnol'd Aleksandrovich", 'Aab Artur Avgustovich', "Aab Artur Vil'gel'movich", "Aab Aelita Arnol'dovna", 'Aab Viktor Aleksandrovich', 'Aab Viktor Aleksandrovich', "Aab Viktor Vil'gel'movich"]

Transliteration can only do so much. Except for proper names, it can
tell you little about the content of the source being transliterated.
Yet the ability to transliterate automatically is of great use when
dealing with lots of names or for people who prefer or need to use ASCII
characters. It is a simple tool but one that can be an enormous time
saver.

Специфика работы в Python со строками на русском языке проистекает из того, что существует множество независимых кодировок для представления на компьютере букв, отличных от латинских. Попробуем ответить на вопросы, что такое кодировка символов, почему их так много, и как нам работать с русскими символами и строками в Python.

Вы, конечно, слышали, что все данные в компьютере представлены в цифровом виде. Компьютер в принципе хранит и обрабатывает только числа.

Однако человек работает с текстами, состоящими из букв, цифр, знаков пунктуации и некоторых специальных символов, например, @, #, $. Посмотрите внимательно на символы, из которых состоит текст на экране компьютера. Вы видите их потому, что компьютер, для передачи данных пользователю, представляет хранящиеся в нем числовые данные в виде символов.

И наоборот, для передачи данных в компьютер пользователь вводит символы с клавиатуры. Посмотрите на клавиатуру и найдите кнопки для ввода букв, цифр, знаков пунктуации и специальных символов %, ^ и &. Введенные вами с клавиатуры символы хранятся в памяти компьютера в виде чисел. Потому что ничего, кроме чисел, в компьютере не может храниться.

Поэтому каждый символ, отображаемый или принимаемый компьютером, кодируется некоторым числом. Ниже представлена таблица кодировки ASCII, которая использует числа от 0 до 127 для кодирования символов, включая латиницу (буквы латинского алфавита), цифры от 0 до 9, знаки пунктуации и специальные символы. Кроме того, коды от 0 до 31 кодируют специальные управляющие символы, такие как табуляция TAB, перевод строки LF и другие. Подробнее познакомиться с таблицей ASCII можно в Википедии.

0 NULL 32 Space 64 @ 96 `
1 SOH 33 ! 65 A 97 a
2 STX 34 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 71 G 103 g
8 BS 40 ( 72 H 104 h
9 TAB 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DC1 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 ETB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 ~
31 US 63 ? 95 _ 127 DEL

Все современные компьютеры и программы понимают и широко используют кодировку ASCII. Вот почему латиница является самым распространенным алфавитом на компьютерах, а англоязычные пользователи компьютеров, по большей части, лишены необходимости задумываться о кодировках символов и переключать раскладку клавиатуры.

Закодируем, используя приведенную выше таблицу кодов ASCII, слово “Hello”. Мы получим следующую последовательностью числовых кодов: 72, 101, 108, 108, 111. Проверить (и узнать) соответствие букв и кодов можно при помощи встроенных функций Python chr и ord. Функция chr принимает в качестве аргумента целочисленный код и возвращает соответствующий ему символ. Функция ord, наоборот, принимает символ и возвращает кодирующее его целое число:

>>> ord('H')
72
>>> ord('e')
101
>>> chr(101)
'e'
>>> type(chr(101))
<type 'str'>
>>>

Посмотрите еще раз на таблицу ASCII. Как видите, в ней нет букв русского алфавита. А также в ней греческих, арабских, японских и других букв и иероглифов, использующихся в разных языках Земли. Для кодирования букв и других символов, отсутствующих в таблице ASCII, используются числа больше 128. На следующем рисунке представлена кодировка cp866, использующая числа от 128 до 255 для кодирования символов кириллицы (букв русского алфавита) и специальных графических символов.

128 А 160 а 192 224 р
129 Б 161 б 193 225 с
130 В 162 в 194 226 т
131 Г 163 г 195 227 у
132 Д 164 д 196 228 ф
133 Е 165 е 197 229 х
134 Ж 166 ж 198 230 ц
135 З 167 з 199 231 ч
136 И 168 и 200 232 ш
137 Й 169 й 201 233 щ
138 К 170 к 202 234 ъ
139 Л 171 л 203 235 ы
140 М 172 м 204 236 ь
141 Н 173 н 205 237 э
142 О 174 о 206 238 ю
143 П 175 п 207 239 я
144 Р 176 208 240 Ё
145 С 177 209 241 ё
146 Т 178 210 242 Є
147 У 179 211 243 є
148 Ф 180 212 244 Ї
149 Х 181 213 245 ї
150 Ц 182 214 246 Ў
151 Ч 183 215 247 ў
152 Ш 184 216 248 °
153 Щ 185 217 249
154 Ъ 186 218 250 ·
155 Ы 187 219 251
156 Ь 188 220 252
157 Э 189 221 253 ¤
158 Ю 190 222 254
159 Я 191 223 255  

Кодировка cp866 использовалась в операционной системе MS DOS и теперь по умолчанию используется в консоли MS Windows. Буквы cp в названии этой и других кодировок — сокращение от code page (англ.: кодовая страница).

Случилось так, что числа от 128 до 255 стали использоваться в разных странах для кодирования букв алфавитов разных языков, а не только русского. Но даже если вести речь только о кириллице, то, кроме кодировки cp866, существуют несколько других кодировок, которые иначе сопоставляют буквы кириллицы кодам в диапазоне от 128 до 255. В качестве примера еще одной кириллической кодировки ниже приведена таблица кодов cp1251, используемая графическими приложениями в ОС MS Windows, такими как Блокнот, MS Office и другими.

128 Ђ 160   192 А 224 а
129 Ѓ 161 Ў 193 Б 225 б
130 162 ў 194 В 226 в
131 ѓ 163 Ј 195 Г 227 г
132 164 ¤ 196 Д 228 д
133 165 Ґ 197 Е 229 е
134 166 ¦ 198 Ж 230 ж
135 167 § 199 З 231 з
136 168 Ё 200 И 232 и
137 169 © 201 Й 233 й
138 Љ 170 Є 202 К 234 к
139 171 « 203 Л 235 л
140 Њ 172 ¬ 204 М 236 м
141 Ќ 173 ­ 205 Н 237 н
142 Ћ 174 ® 206 О 238 о
143 Џ 175 Ї 207 П 239 п
144 ђ 176 ° 208 Р 240 р
145 177 ± 209 С 241 с
146 178 І 210 Т 242 т
147 179 і 211 У 243 у
148 180 ґ 212 Ф 244 ф
149 181 µ 213 Х 245 х
150 182 214 Ц 246 ц
151 183 · 215 Ч 247 ч
152 ˜ 184 ё 216 Ш 248 ш
153 185 217 Щ 249 щ
154 љ 186 є 218 Ъ 250 ъ
155 187 » 219 Ы 251 ы
156 њ 188 ј 220 Ь 252 ь
157 ќ 189 Ѕ 221 Э 253 э
158 ћ 190 ѕ 222 Ю 254 ю
159 џ 191 ї 223 Я 255 я

Из сказанного можно сделать вывод о том, что для правильного отображения символов на экране компьютеру необходимо знать, в какой кодировке представлены данные, которые нужно отобразить. Например, пускай нам дана следующая последовательность кодов: 232, 227, 226. Если принять, что это символы, представленные в кодировке cp866, то мы получим слово “шут”. А если принять, что это символы, представленные в кодировке cp1251, то мы получим слово “игв”. А в греческой кодировке cp1253 эти же коды дадут нам “θγβ”! На сегодняшний день существуют десятки кодировок, сопоставляющих числовые коды от 128 до 255 различным символам!

Если вы запускаете интерпретатор Python в консоли русскоязычной Windows, то Python ожидает, что строки используют кодировку cp866. Давайте проведем небольшое исследование для того, чтобы подтвердить или опровергнуть это утверждение. Воспользуемся функцией ord для получения числовых кодов нескольких русских букв, введенных с клавиатуры, и таблицей кодов cp866, приведенной выше, чтобы убедиться, что функция ord вернула нам коды букв в кодировке cp866:

>>> print ord('э'), ord('ю'), ord('я')
237 238 239
>>>

А функция chr выведет буквы русского алфавита, соответствующие кодам, взятым нами из таблицы cp866:

>>> print chr(128), chr(129), chr(130)
А Б В
>>>

Итак, русские буквы, которые мы вводим с клавиатуры при работе в интерактивном режиме Python, представлены в кодировке cp866. Работая в интерактивном режиме Python, мы можем смело использовать русские буквы в строковых значениях:

>>> name = 'мир'
>>> print 'Привет', name
Привет мир
>>>

Таким образом, все примеры работы в интерактивном режиме, приведенные в книге, можно безболезненно русифицировать, заменяя английские слова и предложения на русские.

Однако, для русификации скриптов Python, сохраненных в файлах, нам осталось сделать еще один шаг. Нам нужно ответить на вопрос, в какой кодировке сохранен наш скрипт в файле? Это зависит от текстового редактора, в котором был написан и сохранен скрипт, и от того, была ли явно указана кодировка при сохранении файла.

Как было сказано выше, Блокнот, или Notepad, простой текстовый редактор, имеющийся в ОС Windows, использует кириллическую кодировку cp1251, а консоль Windows, или окно для работы с командной строкой, по умолчанию использует кириллическую кодировку cp866. Это очень неудобно для русскоязычных пользователей.

Например, создайте в Блокноте файл C:\russian.txt с единственной строкой:

А теперь откройте окно с командной строкой и выведите содержимое этого файла на экран:

C:\>type russian.txt
╧ЁштхЄ ьшЁ!

Что это за кракозябры?

Если вы отыщете эти символы, один за одним, в приведенной выше таблице кодов cp866, то получится последовательность кодов: 207, 240, 232, 226, 229, 242, 32, 252, 248, 240, 33. (Пробел и восклицательный знак имеют коды из диапазона 0 — 127 и кодируются таблицей ASCII.) Теперь переведите эти коды в символы, используя таблицу кодировки cp1251, и вы получите “Привет мир!” Кракозябры в консольном окне мы видим потому, что Блокнот сохранил файл в кодировке cp1251, а консольное окно считает, что коды от 128 до 255 представляют символы из кодировки cp866!

Преодолеть эту проблему можно с помощью консольной команды chcp. Команда chcp без параметров показывает, какая кодировка является текущей:

C:\>chcp
Active code page: 866

А в качестве параметра команда chcp принимает номер кодировки, которую необходимо сделать текущей. Если с ее помощью изменить текущую кодировку консольного окна на cp1251, то мы, наконец, сможем увидеть содержимое файла russian.txt неискаженным:

C:\>chcp 1251
Active code page: 1251

C:\>type russian.txt
Привет мир!

Скрипт на Python является текстовым файлом точно так же, как файл russian.txt, с которым мы экспериментировали. И если создать и сохранить скрипт, использующий русские буквы, в Блокноте, то скрипт будет сохранен в кодировке cp1251. Давайте откроем в Блокноте файл russian.txt и сохраним его как russian.py, слегка изменив его содержимое:

Теперь это файл с очень простым скриптом на языке Python. Выполним его:

C:\>python russian.py
  File "russian.py", line 1
SyntaxError: Non-ASCII character '\xcf' in file russian.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

Вместо ожидаемого приветствия на русском языке Python вывел сообщение об ошибке. Сообщение говорит о том, что в 1-ой строке файла встретился символ, не являющийся символом ASCII, а кодировка не объявлена. Очевидно, что символы, не являющиеся символами ASCII, в нашем файле — это русские буквы. Но что же в этом плохого?

Дело в том, что Python по умолчанию ожидает, что скрипты, переданные ему для выполнения, имеют кодировку ASCII, то есть, содержат символы с кодами в диапазоне 0 — 127. Для всех, кто использует в своих скриптах только латиницу, цифры и другие символы ASCII, это работает прекрасно. Пользователи, использующие в своих программах строковые значения и комментарии на английском языке, чувствуют себя совершенно комфортно в этой ситуации и, по большей части, не подозревают о проблеме, с которой мы только что столкнулись.

Чтобы сообщить Python о том, что скрипт использует кодировку, отличную от ASCII, нужно в начале файла поместить комментарий специального вида, содержащий информацию о кодировке файла. Для скрипта russian.py, созданного в Блокноте, укажем кодировку cp1251, после чего скрипт будет выглядеть так:

# -*- coding: cp1251 -*-

print 'Привет мир!'

После этого сможем успешно выполнить скрипт в консольном окне Windows (только не забудьте установить текущую кодировку командой chcp 1251):

C:\>chcp 1251
Active code page: 1251

C:\>python russian.py
Привет мир!

Итак, для того, чтобы скрипт Python заговорил по-русски в консольном окне Windows, необходимо:

  1. Указать в начале скрипта кодировку, которую использует файл. Например:

  2. Установить в консольном окне Windows кодировку, которую использует выполняемый скрипт. Например:

    C:\> chcp 1251
    Active code page: 1251

В общем случае, скрипт с русскими строками и комментариями может использовать любую из кириллических кодировок, в частности, любую из рассмотренных выше, cp1251 или cp866. Важно, чтобы объявленная в начале файла кодировка была та самая, в которой сохранен файл.

Если скрипт использует кодировку cp866, то в консольном окне русскоязычной Windows не нужно предпринимать никаких специальных действий перед выполнением скрипта, ведь cp866 — кодировка, установленная в консоли по умолчанию. Но если скрипт использует кодировку cp1251, то перед его выполнением в консоли нужно установить текущую кодировку командой chcp 1251.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Что значит защита ресурсов windows не может выполнить запрошенную операцию
  • Ошибка агента обновлений windows 8024500c
  • Как запустить файл от имени администратора в windows 10 если нет строки
  • Как включить планирование графического процессора с аппаратным ускорением в windows 11
  • Windows key кнопка на клавиатуре