繁体   English   中英

用于去除脚本标记的Python正则表达式

[英]Python regular expression to strip script tags

我有点害怕问这个因为害怕报复“你无法用正则表达式解析HTML”邪教。 为什么re.subn(r'<(script).*?</\\1>', '', data, re.DOTALL)不会删除多行'脚本',而只删除最后的两个单行'脚本',请?

谢谢,HC

>>> import re
>>> data = """\
<nothtml> 
  <head> 
    <title>Regular Expression HOWTO &mdash; Python v2.7.1 documentation</title> 
    <script type="text/javascript"> 
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '2.7.1',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script> 
    <script type="text/javascript" src="../_static/jquery.js"></script> 
    <script type="text/javascript" src="../_static/doctools.js"></script>
"""

>>> print (re.subn(r'<(script).*?</\1>', '', data, re.DOTALL)[0])
<nothtml> 
  <head> 
    <title>Regular Expression HOWTO &mdash; Python v2.7.1 documentation</title> 
    <script type="text/javascript"> 
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '2.7.1',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script> 

撇开一般来说这是否是一个好主意的问题,你的例子的问题是re.subn第四个参数是count - Python 2.6中没有flags参数,尽管它是作为Python 2.7中的第五个参数引入的。 相反,你可以在正则表达式的末尾添加`(?s)以获得相同的效果:

>>> print (re.subn(r'<(script).*?</\1>(?s)', '', data)[0])

<nothtml> 
  <head> 
    <title>Regular Expression HOWTO &mdash; Python v2.7.1 documentation</title> 




>>>

...或者如果您使用的是Python 2.7,这应该可行:

>>> print (re.subn(r'<(script).*?</\1>(?s)', '', 0, data)[0])

...即插入0作为count参数。

为了防止它感兴趣,我想我会添加一个额外的答案,显示使用lxml执行此操作的两种方法,我发现它非常适合解析HTML。 (lxml是BeautifulSoup的作者建议的替代方案之一,考虑到后一个库的最新版本的问题。)

添加第一个示例的重点是它非常简单,并且比使用正则表达式删除标记要强大得多。 此外,如果要对文档执行任何更复杂的处理,或者如果要解析的HTML格式不正确,则可以使用可以通过编程方式操作的有效文档树。

删除所有脚本标记

此示例基于lxml文档中的HTMLParser示例

from lxml import etree
from StringIO import StringIO

broken_html = '''
<html> 
  <head> 
    <title>Regular Expression HOWTO &mdash; Python v2.7.1 documentation</title> 
    <script type="text/javascript"> 
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '2.7.1',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script> 
    <script type="text/javascript" src="../_static/jquery.js"></script>
'''

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

for s in tree.xpath('//script'):
    s.getparent().remove(s)

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

这产生了这个输出:

<html>
  <head>
    <title>Regular Expression HOWTO &#8212; Python v2.7.1 documentation</title>
  </head>
</html>

使用lxml的Cleaner模块

另一方面,因为看起来好像你正试图删除像<script>这样的笨拙标签,lxml中的Cleaner模块也会做你喜欢的其他事情:

from lxml.html.clean import Cleaner

broken_html = '''
<html> 
  <head> 
    <title>Regular Expression HOWTO &mdash; Python v2.7.1 documentation</title> 
    <script type="text/javascript"> 
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '2.7.1',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script> 
    <script type="text/javascript" src="../_static/jquery.js"></script>
'''

cleaner = Cleaner(page_structure=False)
print cleaner.clean_html(broken_html)

...产生输出:

<html><head><title>Regular Expression HOWTO — Python v2.7.1 documentation</title></head></html>

(我已经在你的例子nothtml更改为html - 使用原始方法,方法1工作正常,但将所有内容包装在<html><body> ,但方法2因为我没有时间计算的原因不起作用现在出去:))

为了删除html,样式和脚本tages,您可以使用re。

def stripTags(text):
  # scripts = re.compile(r'<script.*?/script>')
  scripts = re.compile(r'<(script).*?</\1>(?s)')
  css = re.compile(r'<style.*?/style>')
  tags = re.compile(r'<.*?>')

  text = scripts.sub('', text)
  text = css.sub('', text)
  text = tags.sub('', text)

我可以轻松工作

简短的回答是,不要这样做。 使用美丽的汤或元素来摆脱它们。 将数据解析为HTML或XML。 正则表达式不起作用,是这个问题的错误答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM