从HTML中删除空节点

时间:2012-02-18 18:09:55

标签: python html

我们正在从一个内容系统迁移到另一个内容系统,并且有大量的HTML,其中有行,例如,像这样:

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

我正在寻找一种用Python剥离HTML的方法,其中没有文本输出到屏幕。因此,与此类似的线将被剥离。

而且,这只是没有文本输出的许多行中的一个例子。所以,我需要找到它们全部剥离。我不必担心图像,电影等,因为在旧的内容管理系统中只能使用文本。

BTW,绝大多数行都以p标记或div标记开头(忽略前导空格)。

4 个答案:

答案 0 :(得分:3)

如果HTML也是一个结构良好的XML文档(这可以通过 HTML-Tidy 之类的工具预先完成),这个转换:

<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>

应用于任何此类XML文档时 - 例如:

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

生成想要的结果,其中字符串值为空或者全部为空格的任何元素都将被删除

<html>

   <body>
      Welcome.


   </body>

</html>

答案 1 :(得分:2)

如果你在Unix机器上,这个python脚本应该可以工作:

#!/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()

答案 2 :(得分:2)

如果HTML文件无效XHTML,我建议安装beautifulsoup4和lxml软件包,并使用以下脚本删除没有文本内容的所有标记,然后从输出中抛出空行:

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

以下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>

打印为:

<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>

答案 3 :(得分: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>