quiero la siguiente funcionalidad.etiquetas de tira python
input : this is test <b> bold text </b> normal text
expected output: this is test normal text
es decir, eliminar el contenido de la etiqueta especificada
quiero la siguiente funcionalidad.etiquetas de tira python
input : this is test <b> bold text </b> normal text
expected output: this is test normal text
es decir, eliminar el contenido de la etiqueta especificada
solución utilizando BeautifulSoup
:
from BeautifulSoup import BeautifulSoup
def removeTag(soup, tagname):
for tag in soup.findAll(tagname):
contents = tag.contents
parent = tag.parent
tag.extract()
s = BeautifulSoup("abcd <b> btag </b> hello <d>dtag</d>")
removeTag(s,"b")
print s
removeTag(s, "d")
print s
devuelve:
>>>
abcd hello <d>dtag</d>
abcd hello
Con BeautifulSoup:
from BeautifulSoup import BeautifulSoup
''.join(BeautifulSoup(page).findAll(text=True))
encontrar en http://www.ghastlyfop.com/blog/2008/12/strip-html-tags-from-string-python.html
+1 por no usar REs en HTML –
@Brain ya he probado este. pero solo elimina la etiqueta, no el contenido que contiene. – developer
@ user283405. Hmm, asegúrate de usar una redacción adecuada. Supongo que lo que necesitas es eliminar el contenido de un elemento (básicamente, algo que comienza con la etiqueta de apertura y termina con la etiqueta de cierre). ¿Derecha? –
Pruebe con:
import re
input = 'this is test <b> bold text </b> normal text'
output = re.compile(r'<[^<]*?/?>').sub('', input)
print output
Regex + HTML = incorrecto. Esencialmente HTML, ya que está (en su mayoría) anidado, no es un lenguaje regular, por lo que no puede ser analizado correctamente por expresiones regulares. Esto es SOlore: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags –
Tienes toda la razón; de todos modos funcionó para el ejemplo OP;). – systempuntoout
En lo que concierne a esta pregunta, no estamos analizando el HTML (es decir, no nos importa qué partes del texto están entre las etiquetas 'abrir' y 'cerrar') y no nos importa cuán profundamente anidadas las etiquetas son, por lo que Regex es una herramienta perfecta para usar. (aunque se cae debido a caracteres '<' que no se encuentran en las etiquetas, como se señala en otras respuestas) –
Si Don No importa Python (aunque las expresiones regulares son bastante genéricas), puede inspirarse en Django's strip_tags filter.
Reproducido aquí para completar -
def strip_tags(value):
"""Returns the given HTML with all tags stripped."""
return re.sub(r'<[^>]*?>', '', force_unicode(value))
EDIT: Si está usando esto, o cualquier otra solución de expresión regular, por favor, tenga en cuenta que se permite el paso de HTML cuidadosamente diseñado (ver comentario), así como Los comentarios HTML y, por lo tanto, no deben usarse con datos que no sean de confianza. Considere utilizar algunas de las respuestas de beautifulsoup, html5lib o lxml para las entradas que no son de confianza.
El filtro 'strip_tags' de Django está roto y casi inútil. Es perfectamente válido poner un carácter '>' en los valores de los atributos, y esto ni siquiera intenta manejar otras construcciones de marcado, como los comentarios. – bobince
De acuerdo (He leído la loca pregunta en algún lugar de StackOverflow tratando de diseñar una expresión regular para analizar HTML :). Personalmente en mi sitio web, utilizo lxml para hacer lo mismo (y también para quitar etiquetas y atributos prohibidos). Creo que la respuesta anterior todavía tiene un uso válido cuando el rendimiento es importante, pero solo debe implementarse teniendo en cuenta esas serias limitaciones. – Sam
Parece que quiere HTMLParser
. (html.parser
en Python 3.)
from HTMLParser import HTMLParser
from sys import stdout
class Filter(HTMLParser):
def __init__(self, ignored_tags):
super(Filter, self).__init__()
self.ignorelevel = 0
self. ignored_tags = ignored_tags
def handle_starttag(self, tag, attrs):
if self.ignorelevel > 0:
self.ignorelevel += 1
elif tag in self.ignored_tags:
self.ignorelevel = 1
else:
# One of these two. Test and see.
stdout.write(self.get_starttag_text())
#stdout.write('<' + self.get_starttag_text() + '>')
def handle_startendtag(self, tag, attrs):
if self.ignorelevel == 0 and tag not in self.ignored_tags:
# One of these two. Test and see.
stdout.write(self.get_starttag_text())
#stdout.write('<' + self.get_starttag_text() + '/>')
def handle_endtag(self, tag):
if self.ignorelevel > 0:
self.ignorelevel -= 1
if self.ignorelevel > 0:
return
stdout.write('</' + tag + '>')
def handle_data(self, data):
stdout.write(data)
def handle_charref(self, name):
stdout.write('&#' + name + ';')
def handle_entityref(self, name):
stdout.write('&' + name + ';')
def handle_comment(self, data):
stdout.write('<!-- ' + data + ' -->')
def handle_decl(self, data):
stdout.write('<!' + data + '>')
def handle_pi(self, data):
stdout.write('<?' + data + '>')
me gustaría utilizar http://code.google.com/p/html5lib/ si desea incluir algunas etiquetas seguras.
Consulte la sección "Tokenizador de higienización" en http://code.google.com/p/html5lib/wiki/UserDocumentation.
Recuerde probar las vulnerabilidades si se trata de un servicio importante: http://ha.ckers.org/xss.html.
respuesta de Sam debe hacer lo que se quería bastante bien por lo que yo puedo decir, pero puede pagar para asegurarse de que cualquier sobrante < > caracteres se reemplazan por & lt; y & gt; respectivamente para evitar el uso indebido/HTML no válido.
Este enfoque tiene la ventaja de que puede aceptar referencias/etiquetas HTML increíblemente malformadas. BeautifulSoup también maneja las etiquetas mal formadas bastante bien, pero html5lib, sgmllib y htmllib pueden ahogarse en el código no válido, algunos más que otros si no recuerdo mal.
El siguiente código también valida & referencias HTML:
import re
from htmlentitydefs import name2codepoint, codepoint2name
S = '1234567890ABCDEF'
DHex = {}
for i in S:
DHex[i.lower()] = None
DHex[i.upper()] = None
def IsHex(S):
if not S: return False
for i in S:
if i not in DHex:
return False
return True
def UnEscape(S, LReEscape=None):
# Converts HTML character references into a unicode string to allow manipulation
#
# If LUnEscape is provided, then the positions of the escaped characters will be
# added to allow turning the result back into HTML with ReEscape below, validating
# the references and escaping all the rest
#
# This is needed to prevent browsers from stripping out e.g.   (spaces) etc
re = LReEscape != None
LRtn = []
L = S.split('&')
xx = 0
yy = 0
for iS in L:
if xx:
LSplit = iS.split(';')
if LSplit[0].lower() in name2codepoint:
# A character reference, e.g. '&'
a = unichr(name2codepoint[LSplit[0].lower()])
LRtn.append(a+';'.join(LSplit[1:]))
if re: LReEscape.append((yy, a))
elif LSplit[0] and LSplit[0][0] == '#' and LSplit[0][1:].isdigit():
# A character number e.g. '4'
a = unichr(int(LSplit[0][1:]))
LRtn.append(a+';'.join(LSplit[1:]))
if re: LReEscape.append((yy, a))
elif LSplit[0] and LSplit[0][0] == '#' and LSplit[0][1:2].lower() == 'x' and IsHex(LSplit[0][2:]):
# A hexadecimal encoded character
a = unichr(int(LSplit[0][2:].lower(), 16)) # Hex -> base 16
LRtn.append(a+';'.join(LSplit[1:]))
if re: LReEscape.append((yy, a))
else: LRtn.append('&%s' % ';'.join(LSplit))
else: LRtn.append(iS)
xx += 1
yy += len(LRtn[-1])
return ''.join(LRtn)
def ReEscape(LReEscape, S, EscFn):
# Re-escapes the output of UnEscape to HTML, ensuring e.g.  
# is turned back again and isn't stripped at a browser level
L = []
prev = 0
for x, c in LReEscape:
if x != prev:
L.append(EscFn(S[prev:x]))
o = ord(c)
if o in codepoint2name:
L.append('&%s;' % codepoint2name[o])
else: L.append('&#%s;' % o)
prev = x+len(c)
L.append(EscFn(S[prev:]))
return ''.join(L)
def escape(value):
# Escape left over <>& tags
value = value.replace('&', '&')
value = value.replace('>', '>')
value = value.replace('<', '<')
return value
def strip_tags(value):
# Strip HTML tags
value = re.sub(r'<[^>]*?>', '', value)
print 'No Tags:', value
# Validate & references
LReEscape = []
value = UnEscape(value, LReEscape)
value = ReEscape(LReEscape, value, EscFn=escape)
print 'References Validated:', value
return value
if __name__ == '__main__':
# Outputs:
# No Tags: this is test bold text normal text >< &blah & &
# References Validated: this is test bold text normal text >< &blah & &
strip_tags('this is test <b> bold text </b> normal text >< &blah & &')
Este código está trabajando tomadas de mi proyecto Supybot, por lo que está bastante bien probado:
class HtmlToText(sgmllib.SGMLParser): """Taken from some eff-bot code on c.l.p.""" entitydefs = htmlentitydefs.entitydefs.copy() entitydefs['nbsp'] = ' ' def __init__(self, tagReplace=' '): self.data = [] self.tagReplace = tagReplace sgmllib.SGMLParser.__init__(self) def unknown_starttag(self, tag, attr): self.data.append(self.tagReplace) def unknown_endtag(self, tag): self.data.append(self.tagReplace) def handle_data(self, data): self.data.append(data) def getText(self): text = ''.join(self.data).strip() return normalizeWhitespace(text) def htmlToText(s, tagReplace=' '): """Turns HTML into text. tagReplace is a string to replace HTML tags with. """ x = HtmlToText(tagReplace) x.feed(s) return x.getText()
Como señala la cadena de documentación, se originó con Fredrik Lundh, no yo.Como se suele decir, grandes autores roban :)
utilizar el módulo webob.exc:
from webob.exc import strip_tags
y luego usarlo:
print strip_tags('a<br/>b')
>> ab
¿Es necesario esto para cualquier etiqueta o simplemente el ejemplo dado ? –
@ cb160 quiero con cualquier etiqueta. es decir, genérico – developer
¿Desea que se quite todas las etiquetas o solo las que enumera? –