2012-02-18 8 views
7

Estamos migrando de un sistema de contenido a otro y tienen toneladas de HTML donde hay líneas, por ejemplo, así:Eliminación de nodos vacíos de HTML

<p style="text-align: justify;"><i> </i></p> 

estoy buscando una manera de despojar HTML con Python donde no hay salida de texto a la pantalla. Entonces una línea similar a esto sería despojada.

Y, este es solo uno de MUCHOS ejemplos de líneas donde no hay salida de texto. Entonces, necesitaría encontrarlos a todos para desnudarse. No tengo que preocuparme por imágenes, películas, etc. ya que solo era posible enviar mensajes de texto en nuestro antiguo sistema de administración de contenido.

BTW, la gran mayoría de las líneas o bien comienzan con una etiqueta p o una etiqueta div (ignorando los espacios en blanco iniciales).

+0

Hmm. ¿Qué pasa con las etiquetas estructurales que están vacías? (divs para uso de JavaScript, por ejemplo) – Cameron

+0

Creo que necesitará un analizador html para eso ... – greg0ire

Respuesta

3

En caso de que el HTML es también un documento XML bien formado (Esto se puede hacer en un paso previo con una herramienta como HTML-Tidy), esta transformación:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*[not(normalize-space(.))]"/> 
</xsl:stylesheet> 

cuando se aplica sobre cualquier tal documento XML - por ejemplo:

<html> 
<body> 
    Welcome. 
    <p style="text-align: justify;"><i> </i></p> 
</body> 
</html> 

produce el resultado deseado en el que cualquier elemento cuyo valor de cadena está vacía o es todos los espacios en blanco, se elimina:

<html> 

    <body> 
     Welcome. 


    </body> 

</html> 
1

Si estás en una máquina Unix, este script en Python debería funcionar:

#!/usr/bin/python 

import sys 
import os 
import subprocess 
import tempfile 

if len(sys.argv) < 2: 
    sys.exit("usage: %s HTML_FILE" % sys.argv[0]) 

stylesheet = ''' 
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:template match="*[string-length(normalize-space(.)) = 0]"/> 

     <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
     </xsl:template> 

    </xsl:stylesheet> 
''' 

stylesheet_file = tempfile.NamedTemporaryFile(suffix='.xslt') 
stylesheet_file.write(stylesheet) 
stylesheet_file.flush() 

p = subprocess.Popen("xsltproc --html %s %s" % (stylesheet_file.name, sys.argv[1]), 
     shell=True, stdout=subprocess.PIPE) 

p.wait() 
sys.stdout.write(p.stdout.read()) 
stylesheet_file.close() 
1

En caso de que el archivo HTML no es válida XHTML, sugiero instalar los paquetes beautifulsoup4 y LXML y utilizando la siguiente secuencia de comandos, que elimina todas las etiquetas sin contenido de texto y luego tira a la basura líneas vacías de la salida:

import sys 
from bs4 import BeautifulSoup, element 
def no_nl(s): 
    return str(s).replace("\r", "").replace("\n", "") 

if len(sys.argv) != 2: 
    print "Usage: %s html_file > output" % sys.argv[0] 
    sys.exit(1) 

soup = BeautifulSoup(open(sys.argv[1])) 

# first we have to get rid of all comments 
for e in soup.find_all(): 
    for x in e.children: 
     if isinstance(x, element.Comment): 
      x.replace_with("") 

for e in soup.find_all(): 
    if not len(no_nl(e.text).strip()): 
     e.extract() 

for s in str(soup).split("\n"): 
    if len(s.strip()): 
     print s 

la siguiente HTML:

<html><head><title>Title</title> 
</head><body> 
<div class="abc"><div> 
<div><div><span> </span> 
</div><![CDATA[ This should vanish from output ]]> </div> 
</div></div><p class="title"> <!--blah blah blah comment to remove--> 
<p class="title"><b>Something</b> here. 
</p><p style="text-align: justify;">aaa<I> x</I><span>blah</span></p> 
<p style="text-align: justify;"><I> </I><span></span> 
<p><i><b> </b></i></p> 
<div style="text-align: justify;"><i> </i></div> 
<p class="txt">Spam, spam, lovely spam. 
<p> </p></body></html> 

se imprime como:

<html><head><title>Title</title></head><body> 
<p class="title"><b>Something</b> here. 
</p><p style="text-align: justify;">aaa<i> x</i><span>blah</span></p> 
<p class="txt">Spam, spam, 
lovely spam.</p> 
</body></html> 
0
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="node()[normalize-space(.)]|@*"> 
     <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
Cuestiones relacionadas