2008-10-09

Кодировка в html5lib

Есть такая замечательная библиотека html5lib, а предназначена она для обработки, в том числе не валидного (не корректного) HTML. Пакет так же имеет код для сериализации DOM, ElementTree, BeautifulSoup и другой хрени в HTML, но этой его частью я не пользуюсь.

Вот простенький пример, для парсинга HTML в DOM:
from html5lib.html5parser import HTMLParser
from html5lib.treebuilders.dom import TreeBuilder

dom = HTMLParser(tree = TreeBuilder).parse(html)
Где html — файловый объект или строка. Собственно это все.

Следует отметить, что это замечательная библиотека в состоянии самостоятельно определить кодировку документа одним из нескольких способов, в том числе «самым правильным», используя значение тега meta. Но вот незадача, «самый правильный» способ берет только первые 512 байт для анализа и, если заголовок большой и тег с указанием кодировки находится за границей в 512 байт, то кодировку определить нет шансов.

Решить проблему можно таким вот хаком:
from html5lib.inputstream import HTMLInputStream

HTMLInputStream.numBytesMeta = property(
lambda self: 1024,
lambda self, value: None)
HTMLInputStream.numBytesChardet = property(
lambda self: 2048,
lambda self, value: None)

del HTMLInputStream
Где numBytesMeta это и есть ограничение при сканировании meta, а numBytesChardet это ограничение при сканировании HTML другим методом, какой анализ проводится, я не разбирался. Эти атрибуты настраиваются при инициализации экземпляра HTMLInputStream и тут же используются, так что другого способа перекрыть эти значения нет, не считая, конечно, варианта с переопределением и полным переписыванием метода __init__ и использованием «хитрых свойств». Я умолчал про цифры в лямбдах, но вы и сами о их смысле догадываетесь.

2 комментария:

nach комментирует...

Большое спасибо за статью! Без вашего топика бы не понял почему на некоторых страничках кодировка не определяется. Правда, вместо переопределения класса я поправил размер буфера прямо в библиотеке. Благослови бог open-source =)

bw комментирует...

> я поправил размер буфера прямо в библиотеке

Дурной тон. Теперь тебе придётся тянуть за собой 11,5 тыс.строк кода и в проектной документации жирным по белому приписать зачем (потому что через месяц забудешь сам, не говоря про других разработчиков). Это же заметно осложняет обновление этой библиотеки (по той же проблеме, поиск причины почему код был взят на борт проекта).

Или ты передал код разработчикам?

Сейчас, если приходится делать подобные хаки, я так же добавляю предупреждение в логирование, в случае не соответствия текущей версии библиотеки, версии, под которую делался хак.