Versão curta!
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 . A versão deles também lida com entidades HTML, enquanto essa rápida não.
Por que não posso simplesmente retirar as tags e deixá-las?
Uma coisa é manter as pessoas longe das <i>italicizing</i>
coisas, sem deixar i
s flutuando. Mas é outra forma de receber informações arbitrárias e torná-las completamente inofensivas. A maioria das técnicas desta página deixará intactos comentários não fechados ( <!--
) e colchetes angulares que não fazem parte das tags ( blah <<<><blah
). A versão HTMLParser pode até deixar tags completas, se elas estiverem em um comentário não fechado.
E se o seu modelo for {{ firstname }} {{ lastname }}
? firstname = '<a'
e lastname = 'href="http://evil.com/">'
será liberado por todos os removedores de tags desta página (exceto @ Medeiros!), porque eles não são tags completos por si próprios. Retirar tags HTML normais não é suficiente.
O Django strip_tags
, uma versão melhorada (veja o próximo cabeçalho) da resposta principal a esta pergunta, dá o seguinte aviso:
Absolutamente nenhuma garantia é fornecida sobre a sequência resultante ser HTML seguro. Portanto, NUNCA marque com segurança o resultado de uma strip_tags
chamada sem escapar primeiro, por exemplo, com escape()
.
Siga os conselhos deles!
Para remover tags com o HTMLParser, você deve executá-lo várias vezes.
É fácil contornar a resposta principal para esta pergunta.
Veja esta string ( fonte e discussão ):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
A primeira vez que o HTMLParser o vê, não é possível dizer que <img...>
é uma tag. Parece quebrado, então o HTMLParser não se livra dele. Só tira o <!-- comments -->
, deixando você com
<img src=x onerror=alert(1);//>
Esse problema foi divulgado ao projeto Django em março de 2014. O antigo strip_tags
era basicamente o mesmo que a principal resposta a essa pergunta. A nova versão deles basicamente roda em um loop até que a execução novamente não mude a string:
# _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
Obviamente, nada disso é um problema se você sempre escapar do resultado strip_tags()
.
Atualização 19 de março de 2015 : Houve um bug nas versões do Django anteriores à 1.4.20, 1.6.11, 1.7.7 e 1.8c1. Essas versões podem inserir um loop infinito na função strip_tags (). A versão fixa é reproduzida acima. Mais detalhes aqui .
Coisas boas para copiar ou usar
Meu código de exemplo não lida com entidades HTML - as versões empacotadas do Django e MarkupSafe.
Meu código de exemplo é extraído da excelente biblioteca MarkupSafe para prevenção de scripts entre sites. É conveniente e rápido (com acelerações em C para sua versão nativa do Python). Ele está incluído no Google App Engine e é usado por Jinja2 (2.7 e superior) , Mako, Pylons e muito mais. Ele funciona facilmente com modelos do Django do Django 1.7.
O strip_tags do Django e outros utilitários html de uma versão recente são bons, mas eu os acho menos convenientes que o MarkupSafe. Eles são bem independentes, você pode copiar o que precisa desse arquivo .
Se você precisar remover quase todas as tags, a biblioteca Bleach é boa. Você pode fazer cumprir regras como "meus usuários podem colocar itálico nas coisas, mas eles não podem criar iframes".
Entenda as propriedades do seu removedor de etiquetas! Execute testes de fuzz nele! Aqui está o código que eu usei para fazer a pesquisa para esta resposta.
observação tímida - A pergunta em si é sobre a impressão no console, mas este é o principal resultado do Google para "python strip html from string"; é por isso que essa resposta é 99% sobre a web.
&
). Você pode 1) removê-los junto com as tags (geralmente indesejáveis e desnecessárias, pois são equivalentes ao texto sem formatação), 2) deixá-los inalterados (uma solução adequada se o texto retirado estiver voltando ao contexto HTML) ou 3 ) decodifique-os para texto sem formatação (se o texto removido estiver entrando em um banco de dados ou em outro contexto não HTML, ou se sua estrutura da Web executar automaticamente a saída de texto HTML para você).