¡Version corta!
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)
Fuente de expresiones regulares: MarkupSafe . Su versión también maneja entidades HTML, mientras que esta rápida no lo hace.
¿Por qué no puedo simplemente quitar las etiquetas y dejarlo?
Una cosa es mantener a las personas alejadas de las <i>italicizing</i>cosas, sin dejar is flotando. Pero otra es tomar aportaciones arbitrarias y hacerlo completamente inofensivo. La mayoría de las técnicas en esta página dejarán intactos elementos como los comentarios no cerrados ( <!--) y los corchetes angulares que no forman parte de las etiquetas ( blah <<<><blah). La versión HTMLParser puede incluso dejar etiquetas completas, si están dentro de un comentario no cerrado.
¿Qué pasa si su plantilla es {{ firstname }} {{ lastname }}? firstname = '<a'y lastname = 'href="http://evil.com/">'todos los separadores de etiquetas de esta página lo dejarán pasar (¡excepto @Medeiros!), porque no son etiquetas completas por sí mismas. Eliminar las etiquetas HTML normales no es suficiente.
Django's strip_tags, una versión mejorada (ver el siguiente encabezado) de la respuesta principal a esta pregunta, da la siguiente advertencia:
Absolutamente NO se proporciona ninguna garantía acerca de que la cadena resultante sea segura para HTML. Por lo tanto, NUNCA marque con seguridad el resultado de una strip_tagsllamada sin escapar primero, por ejemplo con escape().
¡Sigue sus consejos!
Para eliminar etiquetas con HTMLParser, debe ejecutarlo varias veces.
Es fácil eludir la respuesta principal a esta pregunta.
Mire esta cadena ( fuente y discusión ):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
La primera vez que HTMLParser lo ve, no puede decir que <img...>es una etiqueta. Parece roto, por lo que HTMLParser no se deshace de él. Solo saca el <!-- comments -->, dejándote con
<img src=x onerror=alert(1);//>
Este problema fue revelado al proyecto Django en marzo de 2014. Su antiguo strip_tagsera esencialmente el mismo que la respuesta principal a esta pregunta. Su nueva versión básicamente lo ejecuta en un bucle hasta que ejecutarlo nuevamente no cambia la cadena:
# _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
Por supuesto, nada de esto es un problema si siempre escapas del resultado de strip_tags().
Actualización 19 de marzo de 2015 : hubo un error en las versiones de Django anteriores a 1.4.20, 1.6.11, 1.7.7 y 1.8c1. Estas versiones podrían entrar en un bucle infinito en la función strip_tags (). La versión fija se reproduce arriba. Más detalles aquí .
Cosas buenas para copiar o usar
Mi código de ejemplo no maneja entidades HTML, las versiones empaquetadas de Django y MarkupSafe sí.
Mi código de ejemplo se extrae de la excelente biblioteca MarkupSafe para la prevención de secuencias de comandos entre sitios. Es conveniente y rápido (con aceleraciones en C a su versión nativa de Python). Está incluido en Google App Engine y lo utilizan Jinja2 (2.7 y versiones posteriores) , Mako, Pilones y más. Funciona fácilmente con las plantillas de Django de Django 1.7.
Strip_tags de Django y otras utilidades html de una versión reciente son buenas, pero las encuentro menos convenientes que MarkupSafe. Son bastante independientes, puede copiar lo que necesita de este archivo .
Si necesita quitar casi todas las etiquetas, la biblioteca de Bleach es buena. Puede hacer que aplique reglas como "mis usuarios pueden poner en cursiva las cosas, pero no pueden hacer iframes".
¡Comprenda las propiedades de su etiqueta stripper! Ejecute pruebas de fuzz en él! Aquí está el código que usé para hacer la investigación de esta respuesta.
nota tímida : la pregunta en sí misma se trata de imprimir en la consola, pero este es el principal resultado de Google para "python strip html from string", por lo que esta respuesta es 99% sobre la web.
&). Puede 1) eliminarlos junto con las etiquetas (a menudo indeseables e innecesarios, ya que son equivalentes a texto sin formato), 2) dejarlos sin cambios (una solución adecuada si el texto eliminado vuelve directamente a un contexto HTML) o 3 ) los decodifica en texto sin formato (si el texto eliminado se va a una base de datos o algún otro contexto que no sea HTML, o si su marco web realiza automáticamente el escape de texto HTML por usted).