Versione breve!
import re, cgi
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
# Remove well-formed tags, fixing mistakes by legitimate users
no_tags = tag_re.sub('', user_input)
# Clean up anything else by escaping
ready_for_web = cgi.escape(no_tags)
Fonte Regex: MarkupSafe . La loro versione gestisce anche entità HTML, mentre questa veloce no.
Perché non posso semplicemente rimuovere i tag e lasciarlo?
Una cosa è proteggere le persone dalle <i>italicizing</i>cose, senza lasciarle ifluttuare. Ma è un altro prendere input arbitrari e renderlo completamente innocuo. La maggior parte delle tecniche in questa pagina lascerà intatte cose come commenti non chiusi ( <!--) e parentesi angolari che non fanno parte dei tag ( blah <<<><blah). La versione HTMLParser può anche lasciare tag completi, se si trovano all'interno di un commento non chiuso.
E se il tuo modello fosse {{ firstname }} {{ lastname }}? firstname = '<a'e lastname = 'href="http://evil.com/">'saranno lasciati passare da ogni tag stripper su questa pagina (tranne @Medeiros!), perché non sono tag completi da soli. Eliminare i normali tag HTML non è sufficiente.
Django strip_tags, una versione migliorata (vedi intestazione successiva) della risposta principale a questa domanda, dà il seguente avvertimento:
Assolutamente NESSUNA garanzia è fornita sul fatto che la stringa risultante sia HTML sicura. Quindi NON contrassegnare MAI in sicurezza il risultato di una strip_tagschiamata senza prima evitarla, ad esempio con escape().
Segui i loro consigli!
Per rimuovere i tag con HTMLParser, devi eseguirlo più volte.
È facile aggirare la risposta migliore a questa domanda.
Guarda questa stringa ( fonte e discussione ):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
La prima volta che HTMLParser lo vede, non può dire che <img...>è un tag. Sembra rotto, quindi HTMLParser non si sbarazza di esso. Elimina solo il <!-- comments -->, lasciandoti con
<img src=x onerror=alert(1);//>
Questo problema è stato rivelato al progetto Django nel marzo 2014. Il loro vecchio strip_tagsera essenzialmente lo stesso della risposta migliore a questa domanda. La loro nuova versione praticamente lo esegue in un ciclo fino a quando non viene eseguito nuovamente non cambia la stringa:
# _strip_once runs HTMLParser once, pulling out just the text of all the nodes.
def strip_tags(value):
"""Returns the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once.
while '<' in value and '>' in value:
new_value = _strip_once(value)
if len(new_value) >= len(value):
# _strip_once was not able to detect more tags
break
value = new_value
return value
Naturalmente, nulla di tutto questo è un problema se si sfugge sempre al risultato di strip_tags().
Aggiornamento del 19 marzo 2015 : c'era un bug nelle versioni di Django precedenti alla 1.4.20, 1.6.11, 1.7.7 e 1.8c1. Queste versioni potrebbero inserire un ciclo infinito nella funzione strip_tags (). La versione fissa è riprodotta sopra. Maggiori dettagli qui .
Buone cose da copiare o usare
Il mio codice di esempio non gestisce le entità HTML, come invece fanno le versioni in pacchetto Django e MarkupSafe.
Il mio codice di esempio viene estratto dall'eccellente libreria MarkupSafe per la prevenzione degli script tra siti. È comodo e veloce (con accelerazioni C nella versione nativa di Python). È incluso in Google App Engine e utilizzato da Jinja2 (2.7 e versioni successive) , Mako, Pylons e altro. Funziona facilmente con i modelli Django di Django 1.7.
Gli strip_tags di Django e altre utility html di una versione recente sono buoni, ma li trovo meno convenienti di MarkupSafe. Sono piuttosto indipendenti, puoi copiare quello che ti serve da questo file .
Se devi rimuovere quasi tutti i tag, la libreria Bleach è buona. Puoi far applicare regole come "i miei utenti possono scrivere in corsivo le cose, ma non possono creare iframe".
Comprendi le proprietà del tuo tag stripper! Esegui test fuzz su di esso! Ecco il codice che ho usato per fare la ricerca per questa risposta.
nota imbarazzata - La domanda in sé riguarda la stampa sulla console, ma questo è il miglior risultato di Google per "html da stringa in pitone da stringa", quindi questa risposta è del 99% sul web.
&.). È possibile 1) rimuoverli insieme ai tag (spesso indesiderabili e non necessari in quanto equivalenti al testo normale), 2) lasciarli invariati (una soluzione adatta se il testo rimosso viene ripristinato direttamente in un contesto HTML) o 3 ) decodificali in testo semplice (se il testo rimosso viene inserito in un database o in qualche altro contesto non HTML o se il tuo framework web esegue automaticamente l'escaping HTML del testo per te).