class CheckBalancedHTMLParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.stack = Stack() self.balanced = True def handle_starttag(self, tag, attrs): self.stack.push(tag) def handle_endtag(self, tag): if not self.stack.is_empty() and self.stack.peek() == tag: self.stack.pop() else: self.balanced = False def handle_startendtag(self, tag, attrs): pass def handle_data(self, data): pass def is_balanced(self): if not self.stack.is_empty(): self.balanced = False return self.balanced
def handle_endtag(self, tag): # Lorsqu'on rencontre une balise fermante, il faut fabriquer # un arbre avec tous les éléments qui se trouvent sur la pile # jusqu'à ce qu'on rencontre la balise ouvrante qui devra être # la racine de cet arbre. On suppose que le code HTML est # correctement équilibré en balises # la pile tmp_stack est utilisée pour rétablir l'ordre inversé # des sous-arbres qui sont remis sur la pile tmp_stack = Stack() # flag qui indique si la balise ouvrante se trouve au sommet # de la pile. Il faut déjà faire la vérification avant # d'essayer de dépiler des éléments top = self.stack.peek() opening_tag_on_top = (top.tag == tag) # on dépile tous les éléments jusqu'à ce qu'on rencontre au # sommet de la pile la balise ouvrante correspondant à la # balise fermante actuellement traitée. while not opening_tag_on_top: tmp = self.stack.pop() tmp_stack.push(tmp) # on utilise un bloc try, car il se peut que top soit un # objet de type Text (qui ne possède pas d'attribut # tagname) try: top = self.stack.peek() opening_tag_on_top = (top.tag == tag) except: pass # il faut construire un arbre dont la racine est la balise du # sommet de la pile et dont les sous-arbres sont les arbres # qui se trouvent sur la pile tmp_stack tree = self.stack.pop() while not tmp_stack.is_empty(): tree.add_child(tmp_stack.pop()) self.stack.push(tree)
def handle_endtag(self, tag): tmp_stack = Stack() top = self.stack.peek() opening_tag_on_top = (top.tag == tag) while not opening_tag_on_top: tmp = self.stack.pop() tmp_stack.push(tmp) top = self.stack.peek() if top.tag == tag: opening_tag_on_top = True tree = self.stack.pop() while not tmp_stack.is_empty(): tree.add_child(tmp_stack.pop()) self.stack.push(tree)