【问题标题】:Remove all javascript tags and style tags from html with python and the lxml module使用 python 和 lxml 模块从 html 中删除所有 javascript 标签和样式标签
【发布时间】:2012-01-23 03:39:46
【问题描述】:

我正在使用 http://lxml.de/ 库解析一个 html 文档。到目前为止,我已经想出了如何从 html 文档In lxml, how do I remove a tag but retain all contents? 中去除标签,但是该帖子中描述的方法会留下所有文本,在不删除实际脚本的情况下去除标签。我还找到了对 lxml.html.clean.Cleaner http://lxml.de/api/lxml.html.clean.Cleaner-class.html 的类引用,但这对于如何实际使用该类来清理文档很清楚。任何帮助,也许一个简短的例子会对我有所帮助!

【问题讨论】:

    标签: python html lxml


    【解决方案1】:

    您可以轻松使用正则表达式

    对于 Javasript

    def remove_script_code(data):
        clean = re.compile('<script>.*?</script>')
        return [re.sub(clean, '', data)]
    

    对于 CSS 样式

    def remove_style_code(data):
        clean = re.compile('<style>.*?</style>')
        return [re.sub(clean, '', data)]
    

    【讨论】:

      【解决方案2】:

      以下是一些示例,说明如何从 XML/HTML 树中删除和解析不同类型的 HTML 元素。

      关键建议:它有助于依赖外部库并在“native python 2”中完成所有事情 /3 代码”。

      这里有一些示例,说明如何使用“原生”python 执行此操作...

      # (REMOVE <SCRIPT> to </script> and variations)
      pattern = r'<[ ]*script.*?\/[ ]*script[ ]*>'  # mach any char zero or more times
      text = re.sub(pattern, '', text, flags=(re.IGNORECASE | re.MULTILINE | re.DOTALL))
      
      # (REMOVE HTML <STYLE> to </style> and variations)
      pattern = r'<[ ]*style.*?\/[ ]*style[ ]*>'  # mach any char zero or more times
      text = re.sub(pattern, '', text, flags=(re.IGNORECASE | re.MULTILINE | re.DOTALL))
      
      # (REMOVE HTML <META> to </meta> and variations)
      pattern = r'<[ ]*meta.*?>'  # mach any char zero or more times
      text = re.sub(pattern, '', text, flags=(re.IGNORECASE | re.MULTILINE | re.DOTALL))
      
      # (REMOVE HTML COMMENTS <!-- to --> and variations)
      pattern = r'<[ ]*!--.*?--[ ]*>'  # mach any char zero or more times
      text = re.sub(pattern, '', text, flags=(re.IGNORECASE | re.MULTILINE | re.DOTALL))
      
      # (REMOVE HTML DOCTYPE <!DOCTYPE html to > and variations)
      pattern = r'<[ ]*\![ ]*DOCTYPE.*?>'  # mach any char zero or more times
      text = re.sub(pattern, '', text, flags=(re.IGNORECASE | re.MULTILINE | re.DOTALL))
      

      注意:

      re.IGNORECASE # is needed to match case sensitive <script> or <SCRIPT> or <Script>
      re.MULTILINE # is needed to match newlines
      re.DOTALL # is needed to match "special characters" and match "any character" 
      

      我已经在几个不同的 HTML 文件(包括 、 和

      注意:它也确实依赖 beautifulsoup 或任何其他外部下载的库!

      希望这会有所帮助!

      :)

      【讨论】:

        【解决方案3】:

        下面是一个做你想做的事的例子。对于 HTML 文档,Cleaner 是比使用strip_elements 更好的通用解决方案,因为在这种情况下,您希望去除的不仅仅是&lt;script&gt; 标记;您还想摆脱其他标签上的 onclick=function() 属性之类的东西。

        #!/usr/bin/env python
        
        import lxml
        from lxml.html.clean import Cleaner
        
        cleaner = Cleaner()
        cleaner.javascript = True # This is True because we want to activate the javascript filter
        cleaner.style = True      # This is True because we want to activate the styles & stylesheet filter
        
        print("WITH JAVASCRIPT & STYLES")
        print(lxml.html.tostring(lxml.html.parse('http://www.google.com')))
        print("WITHOUT JAVASCRIPT & STYLES")
        print(lxml.html.tostring(cleaner.clean_html(lxml.html.parse('http://www.google.com'))))
        

        您可以在lxml.html.clean.Cleaner documentation 中获取可以设置的选项列表;一些选项可以设置为TrueFalse(默认),而其他选项则采用如下列表:

        cleaner.kill_tags = ['a', 'h1']
        cleaner.remove_tags = ['p']
        

        注意kill和remove的区别:

        remove_tags:
          A list of tags to remove. Only the tags will be removed, their content will get pulled up into the parent tag.
        kill_tags:
          A list of tags to kill. Killing also removes the tag's content, i.e. the whole subtree, not just the tag itself.
        allow_tags:
          A list of tags to include (default include all).
        

        【讨论】:

        • 我大部分时间都在外面,我想应该早点提出这个问题。我只是在玩了这个之后才注意到 kill_tags 的东西似乎实际上并没有做任何事情,例如我添加了cleaner.kill_tags = ('img','noscript','a') 但这些标签仍保留在输出文档中,上面示例的其余部分按预期工作,只是在玩了之后杀死我注意到这一点的标签。
        • 请注意,在我的示例中,我使用方括号,而不是圆括号。你应该试试['img','noscript','a']。方括号表示一个列表,而括号表示一个元组(在您的示例中是一个 3 元素元组)。元组和列表根本不一样。
        • list和tuple我都试过了,notations效果是一样的,标签没有去掉。经过进一步研究,我认为这是与 ubuntu 一起分发的 lxml/html/clean.py 版本中的一个错误。注意lxml.de/api/lxml.html.clean-pysrc.htmlkill_tags 的第 253 行在 Ubuntu 附带的 clean.py 版本中初始化为 kill_tags = set(self.kill_tags or ()),它刚刚初始化为 kill_tags = set()。渲染它无效。谢谢,我会通知包维护者。
        • 它不适用于以下网址:blog.cryptographyengineering.com/2016/03/…
        • 清洁剂真的很重要!
        【解决方案4】:

        您也可以为此目的使用 bs4 库。

        soup = BeautifulSoup(html_src, "lxml")
        [x.extract() for x in soup.findAll(['script', 'style'])]
        

        【讨论】:

        • 这肯定是相反的/你如何处理这个列表?
        • 不,因为它在这个过程中改变了soup。即汤不再有这些标签
        【解决方案5】:

        您可以使用strip_elements方法删除脚本,然后使用strip_tags方法删除其他标签:

        etree.strip_elements(fragment, 'script')
        etree.strip_tags(fragment, 'a', 'p') # and other tags that you want to remove
        

        【讨论】:

        • 对于 HTML 文档,在删除脚本时,您希望摆脱所有 javascript,而不仅仅是 &lt;script&gt; 标记本身,所以 Cleaner 是 better general solution,尽管 strip_elements 对于XML 文档。
        • 谢谢...您的回答对于 XML 文档来说仍然是一个很好的解决方案,所以我在回答中添加了一些文本来阐明 XML 与 HTML 用例。
        猜你喜欢
        • 1970-01-01
        • 2012-07-13
        • 1970-01-01
        • 2011-02-26
        • 2011-07-10
        • 2020-03-08
        • 2014-10-08
        • 2020-02-15
        • 1970-01-01
        相关资源
        最近更新 更多