ho completamente rispettare utilizzando Beautiful Soup per ottenere contenuti reso, ma non può essere il pacchetto ideale per acquisire il contenuto visualizzato su una pagina.
Ho avuto un problema simile per ottenere il rendering del contenuto o il contenuto visibile in un browser tipico. In particolare, ho avuto molti casi atipici per lavorare con un esempio così semplice di seguito. In questo caso il tag non visualizzabile è nidificato in un tag di stile e non è visibile in molti browser che ho selezionato. Esistono altre varianti come la definizione di un'impostazione di un'etichetta di classe su none. Quindi usando questa classe per il div.
<html>
<title> Title here</title>
<body>
lots of text here <p> <br>
<h1> even headings </h1>
<style type="text/css">
<div > this will not be visible </div>
</style>
</body>
</html>
Una soluzione postato sopra è:
html = Utilities.ReadFile('simple.html')
soup = BeautifulSoup.BeautifulSoup(html)
texts = soup.findAll(text=True)
visible_texts = filter(visible, texts)
print(visible_texts)
[u'\n', u'\n', u'\n\n lots of text here ', u' ', u'\n', u' even headings ', u'\n', u' this will not be visible ', u'\n', u'\n']
Questa soluzione ha certamente applicazioni in molti casi, e fa il lavoro abbastanza bene in generale ma in html postato sopra mantiene il testo che non viene eseguito il rendering. Dopo la ricerca quindi un paio di soluzioni venuto qui BeautifulSoup get_text does not strip all tags and JavaScript e qui Rendered HTML to plain text using Python
ho provato entrambe le soluzioni: html2text e nltk.clean_html e sono rimasto sorpreso dai risultati di temporizzazione così pensavano garantiti una risposta per i posteri. Ovviamente le velocità dipendono molto dal contenuto dei dati ...
Una risposta qui da @Helge riguardava l'utilizzo di nltk di tutte le cose.
import nltk
%timeit nltk.clean_html(html)
was returning 153 us per loop
Ha funzionato molto bene per restituire una stringa con il rendering html. Questo modulo nltk era più veloce persino di html2text, anche se forse html2text è più robusto.
betterHTML = html.decode(errors='ignore')
%timeit html2text.html2text(betterHTML)
%3.09 ms per loop
@jbochi Ho sostituito la riga 3 di visible() con re.match ('. * . * ', string, re.DOTALL). Il tuo sembra funzionare solo se il * intero * contenuto del testo è un commento, ma se c'è uno spazio iniziale o una nuova riga allora verrà restituito l'html 'invisibile'. La mia soluzione è eccessivamente aggressiva in quanto segnerà l'intero elemento come invisibile, ma per i miei scopi va benissimo. – Trindaz
+1 per 'soup.findAll (text = True)' non sapeva mai di quella funzione –
Per BS4 recente (almeno) è possibile identificare i commenti con 'isinstance (element, Comment)' invece di corrispondere con una regex. – tripleee