HTML кодирование и разбор lxml

Я пытаюсь, наконец, решить некоторые проблемы с кодированием, которые возникают при попытке очистить HTML с помощью lxml. Вот три примера HTML-документов, с которыми я столкнулся:

1.

<!DOCTYPE html>
<html lang='en'>
<head>
   <title>Unicode Chars: 은 —’</title>
   <meta charset='utf-8'>
</head>
<body></body>
</html>

2.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko-KR" lang="ko-KR">
<head>
    <title>Unicode Chars: 은 —’</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body></body>
</html>

3.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Unicode Chars: 은 —’</title>
</head>
<body></body>
</html>

Мой основной скрипт:

from lxml.html import fromstring
...

doc = fromstring(raw_html)
title = doc.xpath('//title/text()')[0]
print title

Результаты:

Unicode Chars: ì ââ
Unicode Chars: 은 —’
Unicode Chars: 은 —’

Итак, очевидно, проблема с образцом 1 и отсутствующим<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> тег. Решение отВот правильно распознает образец 1 как utf-8, и поэтому он функционально эквивалентен моему исходному коду.

Документы lxml выглядят конфликтующими:

ИзВот пример показывает, что мы должны использовать UnicodeDammit для кодирования разметки как Unicode.

from BeautifulSoup import UnicodeDammit

def decode_html(html_string):
    converted = UnicodeDammit(html_string, isHTML=True)
    if not converted.unicode:
        raise UnicodeDecodeError(
            "Failed to detect encoding, tried [%s]",
            ', '.join(converted.triedEncodings))
    # print converted.originalEncoding
    return converted.unicode

root = lxml.html.fromstring(decode_html(tag_soup))

тем не мениеВот это говорит:

[Y] вы получите ошибки, когда вы попытаетесь [проанализировать] HTML-данные в строке Unicode, которая указывает кодировку в метатеге заголовка. Как правило, следует избегать преобразования данных XML / HTML в Unicode, прежде чем передавать их в анализаторы. Это медленнее и подвержено ошибкам.

Если я попытаюсь следовать первому предложению в документации lxml, мой код будет таким:

from lxml.html import fromstring
from bs4 import UnicodeDammit
...
dammit = UnicodeDammit(raw_html)
doc = fromstring(dammit.unicode_markup)
title = doc.xpath('//title/text()')[0]
print title

Теперь я получаю следующие результаты:

Unicode Chars: 은 —’
Unicode Chars: 은 —’
ValueError: Unicode strings with encoding declaration are not supported.

Пример 1 теперь работает правильно, но пример 3 приводит к ошибке из-за<?xml version="1.0" encoding="utf-8"?> тег.

Есть ли правильный способ справиться со всеми этими случаями? Есть ли лучшее решение, чем следующее?

dammit = UnicodeDammit(raw_html)
try:
    doc = fromstring(dammit.unicode_markup)
except ValueError:
    doc = fromstring(raw_html)

Ответы на вопрос(2)

Ваш ответ на вопрос