使用 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
更好的通用解决方案,因为在这种情况下,您希望去除的不仅仅是<script>
标记;您还想摆脱其他标签上的 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 中获取可以设置的选项列表;一些选项可以设置为True
或False
(默认),而其他选项则采用如下列表:
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,而不仅仅是<script>
标记本身,所以 Cleaner 是 better general solution,尽管 strip_elements
对于XML 文档。
谢谢...您的回答对于 XML 文档来说仍然是一个很好的解决方案,所以我在回答中添加了一些文本来阐明 XML 与 HTML 用例。以上是关于使用 python 和 lxml 模块从 html 中删除所有 javascript 标签和样式标签的主要内容,如果未能解决你的问题,请参考以下文章
python模块--BeautifulSoup4 和 lxml
Python爬虫基础——XPath语法的学习与lxml模块的使用
Python爬虫解析htm时lxml的HtmlElement对象获取和设置inner html方法