# il testo è implicitamente racchiuso nel tag '_text_' import html class HTMLNode: def __init__(self, tag, attributi={}, content=[], chiuso=True): self.tag = tag self.attributi = attributi self.content = content self.chiuso = chiuso def string_tree(self, livello=0): stringa = '\n' stringa += ' '*livello + str(self) if not self.istesto(): for tag in self.content: stringa += tag.string_tree(livello+1) return stringa def html_text(self): stringa = '\n' stringa += self.apri_tag() if not self.istesto(): for tag in self.content: stringa += tag.html_text() else: stringa += self.content if self.chiuso: stringa += self.chiudi_tag() return stringa def apri_tag(self): if self.istesto(): return '' else: stringa = '<' + self.tag for k,v in self.attributi.items(): stringa += ' {}="{}"'.format(k,html.escape(v)) stringa += '>' return stringa def chiudi_tag(self): if self.istesto(): return '' else: return "".format(self.tag) def istesto(self): return self.tag == '_text_' def __str__(self): return "<{}>".format(self.tag) def estrai_tag(DOM, tag): if DOM.tag == tag: return DOM elif DOM.istesto(): return None else: for t in DOM.content: risultato = estrai_tag(t, tag) if risultato: return risultato return None def profondita_massima(DOM): if DOM.istesto(): return 1 elif not DOM.chiuso: return 1 else: massimo = 0 for t in DOM.content: pm = profondita_massima(t) if pm > massimo: massimo = pm return massimo + 1 def num_tag(DOM): if DOM.istesto(): return 1 elif not DOM.chiuso: return 1 else: somma = 1 for t in DOM.content: somma += num_tag(t) return somma import html.parser class _MyHTMLParser(html.parser.HTMLParser): def __init__(self): '''Crea un parser per la class HTMLNode''' # inizializza la class base super() super().__init__() self.root = None self.stack = [] def handle_starttag(self, tag, attrs): '''Metodo invocato per tag aperti''' closed = tag not in ['img','br'] node = HTMLNode(tag,dict(attrs),[],closed) if not self.root: self.root = node if self.stack: self.stack[-1].content.append(node) if closed: self.stack.append(node) def handle_endtag(self, tag): '''Metodo invocato per tag chiusi''' if self.stack and self.stack[-1].tag == tag: self.stack[-1].opentag = False self.stack = self.stack[:-1] def handle_data(self, data): '''Metodo invocato per il testo''' if not self.stack: return self.stack[-1].content.append( HTMLNode('_text_',{},data)) def handle_comment(self, data): '''Metodo invocato per commenti HTML''' pass def handle_entityref(self, name): '''Metodo invocato per caratteri speciali''' if name in name2codepoint: c = unichr(name2codepoint[name]) else: c = '&'+name if not self.stack: return self.stack[-1].content.append( HTMLNode('_text_',{},c)) def handle_charref(self, name): '''Metodo invocato per caratteri speciali''' if name.startswith('x'): c = unichr(int(name[1:], 16)) else: c = unichr(int(name)) if not self.stack: return self.stack[-1].content.append( HTMLNode('_text_',{},c)) def handle_decl(self, data): '''Metodo invocato per le direttive HTML''' pass def parse(html): '''Esegue il parsing HTML del testo html e ritorna la radice dell'albero.''' parser = _MyHTMLParser() parser.feed(html) return parser.root def fparse(fhtml): '''Esegue il parsing HTML del file fhtml e ritorna la radice dell'albero .''' with open(fhtml) as f: root = parse(f.read()) return root if __name__ == '__main__': dom = HTMLNode('div', {}, [ HTMLNode('h1', {}, [ HTMLNode('_text_', {}, "Intestazione della pagina"), ]), HTMLNode('img', {'src': '3cime.png'}, [], chiuso=False), HTMLNode('br', {}, [], chiuso=False), HTMLNode('_text_', {}, "Le tre cime di Lavaredo sono "), HTMLNode('b', {}, [ HTMLNode('_text_', {}, "bellissime"), ]), HTMLNode('_text_', {}, "(vero?)"), ]) print(dom.string_tree()) print(dom.html_text()) with open("paginetta.html", mode="w") as f: f.write(dom.html_text()) ris = estrai_tag(dom, 'img') print(ris.html_text()) print('profondità ', profondita_massima(dom)) print('num. nodi ', num_tag(dom)) paginona = fparse('python_doc.html') print('profondità ', profondita_massima(paginona)) print('num. nodi ', num_tag(paginona)) print(paginona.string_tree()) print(estrai_tag(paginona,'a').html_text())