【问题标题】:How can i remove <p> </p> with python sub如何使用 python sub 删除 <p> </p>
【发布时间】:2011-03-23 13:55:59
【问题描述】:

我有一个 html 文件,我想用空格替换空段落。

mystring = "This <p></p><p>is a test</p><p></p><p></p>"
result = mystring.sub("<p></p>" , "&nbsp;")

这不起作用。

【问题讨论】:

  • ... 请记住,正则表达式肯定会在某人的格式错误的 html 上失​​败,例如 '

    This

    is a

    测试

    '

标签: python html string


【解决方案1】:

don't try to parse HTML with regular expressions。使用适当的解析模块,如htmlparserBeautifulSoup 来实现这一点。现在“忍受”短暂的学习曲线并从中受益:

  1. 您的解析代码将更加健壮,可以处理您可能没有考虑过的极端情况,这些情况会因正则表达式而失败
  2. 对于未来的 HTML 解析/修改任务,您将能够更快地完成任务,因此时间投资最终也会得到回报。

你不会后悔的!保证利润!

【讨论】:

  • 它已经是我被聘用的公司中的现有代码,他们想要更改正则表达式......我怀疑它很快就会失败。我将尝试转向更强大的解决方案。
【解决方案2】:

我认为给出一个如何使用真正的解析器执行此操作的示例总是很好的,并且只是重复Eli Bendersky 在他的回答中给出的合理建议。

下面是一个示例,说明如何使用 lxml 删除空的 &lt;p&gt; 元素。 lxml 的HTMLParser 处理 HTML 非常好。

from lxml import etree
from StringIO import StringIO

input = '''This <p> </p><p>is a test</p><p></p><p><b>Bye.</b></p>'''

parser = etree.HTMLParser()
tree = etree.parse(StringIO(input), parser)

for p in tree.xpath("//p"):
    if len(p):
        continue
    t = p.text
    if not (t and t.strip()):
        p.getparent().remove(p)

print etree.tostring(tree.getroot(), pretty_print=True)

...产生输出:

<html>
  <body>
    <p>This </p>
    <p>is a test</p>
    <p>
      <b>Bye.</b>
    </p>
  </body>
</html>

请注意,我在回复此问题时误读了问题,我只是删除了空的 &lt;p&gt; 元素,而不是用 &amp;nbsp 替换它们。使用 lxml,我不确定一个简单的方法来做到这一点,所以我创建了另一个问题要问:

【讨论】:

  • ++ 是一个真实的例子,但你无缘无故抹黑BeautifulSoup。您链接到的页面明确表示它是旧版本且具有历史意义,并且该模块不再存在这些问题
  • @Eli Bendersky:感谢您纠正这种误解,我现在已经从我的答案中删除了那一点。我没有意识到情况发生了变化,也没有重新阅读我链接到的页面 - 过失......
  • 这个sn-p有一个bug。如果 p 的所有文本内容都包含在另一个元素 - &lt;p&gt;&lt;b&gt;This will be dropped&lt;/b&gt;&lt;/p&gt; 中,则上面的代码将删除它,因为 node.text 仅包含开始标记和第一个孩子的开始之间存在的文本。
  • @abhaga:哎呀,感谢您指出这一点。我已经更新了我的答案。
【解决方案3】:

我认为对于这个特殊的问题,解析模块将是多余的

就是那个函数:

>>> mystring = "This <p></p><p>is a test</p><p></p><p></p>"

>>> mystring.replace("<p></p>","&nbsp;")
'This &nbsp;<p>is a test</p>&nbsp;&nbsp;'

【讨论】:

    【解决方案4】:

    如果&lt;p&gt; 输入为&lt;P&gt;&lt; p &gt;,或者添加了属性,或者使用空标记语法&lt;P/&gt; 给出,该怎么办? Pyparsing 的 HTML 标记支持处理所有这些变体:

    from pyparsing import makeHTMLTags, replaceWith, withAttribute
    
    mystring = 'This <p></p><p>is a test</p><p align="left"></p><P> </p><P/>'
    
    p,pEnd = makeHTMLTags("P")
    emptyP = p.copy().setParseAction(withAttribute(empty=True))
    
    null_paragraph = emptyP | p+pEnd
    null_paragraph.setParseAction(replaceWith("&nbsp;"))
    
    print null_paragraph.transformString(mystring)
    

    打印:

    This &nbsp;<p>is a test</p>&nbsp;&nbsp;&nbsp;
    

    【讨论】:

      【解决方案5】:

      使用正则表达式?

      import re
      result = re.sub("<p>\s*</p>","&nbsp;", mystring, flags=re.MULTILINE)
      

      如果您经常使用,请编译正则表达式。

      【讨论】:

        【解决方案6】:

        我写了那个代码:

        from lxml import etree
        from StringIO import StringIO
        
        html_tags = """<div><ul><li>PID temperature controller</li> <li>Smart and reliable</li> <li>Auto-diagnosing</li> <li>Auto setting</li> <li>Intelligent control</li> <li>2-Rows 4-Digits LED display</li> <li>Widely applied in the display and control of the parameter of temperature, pressure, flow, and liquid level</li> <li>     </li> <p> </p></ul> <div> </div></div>"""
        
        document = etree.iterparse(StringIO(html_tags), html=True)
        
        for a, e in document:
            if not (e.text and e.text.strip()) and len(e) == 0:
                e.getparent().remove(e)
        
        print etree.tostring(document.root)
        

        【讨论】:

        • 为什么投反对票?这是一个可行的解决方案。但值得注意的是,lxml 返回了一个有效的 HTML 字符串。所以输入字符串将被包裹在 和 标签中。因此,给定示例字符串的输出为:“

          This

          is a test

        猜你喜欢
        • 1970-01-01
        • 2018-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多