На этом шаге мы рассмотрим методы решения указанной задачи.
Документы в Интернете могут быть представлены в различных кодировках. Чтобы документ был правильно обработан, необходимо знать его кодировку. Определить кодировку можно по заголовку Content-Type в заголовках ответа Web-сервера:
Content-Type: text/html; charset=utf-8
Кодировку Web-страницы можно также определить по значению параметра content тега <meta>, расположенного в разделе HEAD:
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
Однако часто встречается ситуация, когда кодировка в ответе сервера не совпадает с кодировкой, указанной в теге <meta>, или же таковая вообще не указана. Определить кодировку документа в этом случае позволяет библиотека chardet. Установить ее можно из репозитория PyPI способом, описанным на 228 шаге. Открываем командную строку и набираем в ней команду:
c:\python34\scripts\pip install chardet
Через некоторое время библиотека будет установлена.
Для проверки установки запускаем редактор IDLE и в окне Python Shell выполняем следующий код:
>>> import chardet >>> chardet.__version__ '3.0.4'
Определить кодировку строки позволяет функция detect (<Последовательность байтов>) из модуля chardet. В качестве результата она возвращает словарь с тремя элементами. Ключ encoding содержит название кодировки, ключ language - название языка, а ключ confidence - коэффициент точности определения в виде вещественного числа от 0 до 1. Пример определения кодировки приведен ниже.
>>> import chardet >>> chardet.detect(bytes("Строка", "cp1251")) {'encoding': 'windows-1251', 'language': 'Russian', 'confidence': 0.99} >>> chardet.detect(bytes("Строка", "utf-8")) {'encoding': 'utf-8', 'language': '', 'confidence': 0.99}
Если файл имеет большой размер, то вместо считывания его целиком в строку и использования функции detect() можно воспользоваться классом UniversalDetector. В этом случае можно читать файл построчно и передавать текущую строку методу feed(). Если определение кодировки прошло успешно, атрибут done будет иметь значение True. Это условие можно использовать для выхода из цикла. После окончания проверки следует вызвать метод close(). Получить результат определения кодировки позволяет атрибут result. Очистить результат и подготовить объект к дальнейшему определению кодировки можно с помощью метода reset(). Пример использования класса UniversalDetector приведен ниже.
from chardet.universaldetector import UniversalDetector ud = UniversalDetector() # Создаем объект for line in open("file.txt", "rb"): ud.feed(line) # Передаем текущую строку if ud.done: break # Прерываем цикл, если done == True ud.close() # Закрываем объект print(ud.result) # Выводим результат
Результат работы приложения:
{'confidence': 0.8726928676836571, 'encoding': 'MacCyrillic', 'language': 'Russian'}
Как показали тесты, при использовании кодировки Windows-1251 файл просматривается полностью, и определение кодировки файла, содержащего 6500 строк, занимает почти секунду. Если сменить кодировку файла на UTF-8 без ВОМ, то время определения увеличивается до 5 секунд. Использовать класс UniversalDetector или нет - решать вам.
Со следующего шага мы начнем рассматривать сжатие данных.