使用 python 和 lxml 模块从 html 中删除所有 javascript 标签和样式标签

Posted

技术标签:

【中文标题】使用 python 和 lxml 模块从 html 中删除所有 javascript 标签和样式标签【英文标题】:Remove all javascript tags and style tags from html with python and the lxml module 【发布时间】: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 的类引用,但这对于如何实际使用该类来清理文档很清楚。任何帮助,也许一个简短的例子会对我有所帮助!

【问题讨论】:

【参考方案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 用例。

以上是关于使用 python 和 lxml 模块从 html 中删除所有 javascript 标签和样式标签的主要内容,如果未能解决你的问题,请参考以下文章

Python 之lxml解析模块

python模块--BeautifulSoup4 和 lxml

Python爬虫基础——XPath语法的学习与lxml模块的使用

Python爬虫解析htm时lxml的HtmlElement对象获取和设置inner html方法

使用由 Python 编写的 lxml 实现高性能 XML 解析

windows下使用pip安装python模块lxml