Я пытаюсь найти способ анализировать (потенциально искаженный) HTML в Python и, если выполняется набор условий, выводить этот фрагмент документа с позицией (строка, столбец). Информация о местоположении - это то, что сбивает меня с толку. И чтобы было ясно, мне не нужно строить дерево объектов. Я просто хочу найти определенные фрагменты данных и их положение в исходном документе (подумайте, например, о проверке орфографии: «слово «foo» в строке x, столбце y написано с ошибкой)».
В качестве примера я хочу что-то вроде этого (используя Target API ElementTree):
import xml.etree.ElementTree as ET
class EchoTarget:
def start(self, tag, attrib):
if somecondition():
print "start", tag, attrib, self.getpos()
def end(self, tag):
if somecondition():
print "end", tag, self.getpos()
def data(self, data):
if somecondition():
print "data", repr(data), self.getpos()
target = EchoTarget()
parser = ET.XMLParser(target=target)
parser.feed("<p>some text</p>")
parser.close()
Однако, насколько я могу судить, метода getpos()
(или чего-то подобного) не существует. И, конечно же, это использование синтаксического анализатора XML. Я хочу проанализировать потенциально искаженный HTML.
Интересно, что класс HTMLParser в стандартной библиотеке Python поддерживает получение местоположения. info (с методом getpos()
), но он ужасно обрабатывает деформированный HTML и был исключен как возможное решение. Мне нужно разобрать HTML, который существует в реальном слове, не нарушая синтаксический анализатор.
Я знаю два парсера HTML, которые хорошо работают при анализе искаженного HTML, а именно lxml и html5lib. И на самом деле, я бы предпочел использовать любой из них любым другим вариантам, доступным в Python.
Однако, насколько я могу судить, html5lib не предлагает API событий и требует, чтобы документ анализировался в объект дерева. Тогда мне пришлось бы перебирать дерево. Конечно, к этому моменту связь с исходным документом отсутствует, и вся информация о местоположении теряется. Итак, html5lib отсутствует, и это позор, потому что он кажется лучшим парсером для обработки искаженного HTML.
Библиотека lxml предлагает целевой API, который в основном отражает ElementTree, но опять же, я не знаю никакого способа получить доступ к информации о местоположении для каждого события. Взгляд на исходный код также не дал никаких подсказок.
lxml также предлагает API для событий SAX. Интересно, что в стандартной библиотеке Python упоминается, что SAX поддерживает объекты локатора., но предлагает мало документации о том, как их использовать. Этот SO Question содержит некоторую информацию (при использовании SAX Parser), но я не понимаю, как это связано с ограниченной поддержкой событий SAX, которую предоставляет lxml.
Наконец, прежде чем кто-либо предложит Beautiful Soup, я отмечу, что, как указано на главной странице , «Beautiful Soup работает поверх популярных парсеров Python, таких как lxml и html5lib». Все, что он мне дает, — это объект для извлечения данных без связи с исходным документом. Как и в случае с html5lib, вся информация о местоположении теряется к тому времени, когда я получаю доступ к данным. Мне нужен/нужен необработанный доступ к парсеру напрямую.
Чтобы расширить пример проверки орфографии, о котором я упоминал в начале, я хотел бы проверять правописание только слов в тексте документа (но не имен тегов или атрибутов) и, возможно, захотеть пропустить проверку содержимого определенных тегов (например, скрипт или теги кода). Поэтому мне нужен настоящий парсер HTML. Однако меня интересует только положение слов с ошибками в исходном документе, когда дело доходит до сообщения о словах с ошибками, и мне не нужно строить объект дерева. Чтобы было ясно, это только пример одного потенциального использования. Я могу использовать его для чего-то совершенно другого, но потребности будут по существу теми же. На самом деле, когда-то я создал что-то очень похожее с помощью HTMLParser, но никогда не использовал его, так как обработка ошибок не работала для этого варианта использования. Это было много лет назад, и я, кажется, где-то потерял этот файл. На этот раз я бы хотел использовать lxml или html5lib.
Итак, есть что-то, что я упускаю? Мне трудно поверить, что ни один из этих парсеров (кроме в основном бесполезного HTMLParser) не имеет никакого доступа к информации о позиции. Но если они это делают, это должно быть недокументировано, что мне кажется странным.