В то время как ответ от @ Ajax1234 содержит хороший python + beautifulsoup, я обнаружил, что он очень нестабилен. Главным образом потому, что мне нужна точная строка тега html. Каждый тег, найденный методом, должен присутствовать в HTML-тексте. Это приводит к следующим проблемам:
Он анализирует имена тегов и атрибуты из HTML и подключает их
вместе, чтобы сформировать строку тега yield f'<{_d.name}>' if not _attrs else f'<{_d.name} {_attrs}>'
. Это избавляет от лишних пробелов в теге: <p >
становится <p>
Всегда генерирует закрывающий тег, даже если в разметке его нет
Сбой для атрибутов, которые являются списками: <p class="a b">
становится <p class="[a, b]">
Проблема пробелов может быть частично решена путем очистки HTML перед его обработкой. Я использовал отбеливатель , но это может быть слишком агрессивным. В частности, вы должны указать список принятых тегов, прежде чем использовать его.
Лучший подход - это тонкая оболочка вокруг html.parser.HTMLParser .
Это то, что я уже начал в своем вопросе, разница здесь в том, что я автоматически добавляю генерирующий закрывающий тег.
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.tags = []
def handle_starttag(self, tag, attrs):
self.tags.append(self.get_starttag_text())
def handle_endtag(self, tag):
self.tags.append(f"</{tag}>")
parser = MyHTMLParser();
parser.feed("""<p > Argh, whitespace and p is not closed </a>""")
parser.tags # ['<p >', '</a>']
Это решило проблемы, упомянутые выше, но у него есть один недостаток, он не смотрит на фактический текст для закрывающего тега. Если в закрывающем теге есть дополнительные аргументы или пробелы, при синтаксическом анализе они не будут отображаться.