从HTML中移除脚本标签和on属性
我有一段HTML代码,我需要把里面的脚本标签和任何与脚本相关的属性去掉。这里说的与脚本相关的属性是指那些以“on”开头的属性。
<body>
<script src="...">
</script>
<div onresize="CreateFixedHeaders()" onscroll="CreateFixedHeaders()" id="oReportDiv" style="overflow:auto;WIDTH:100%">
<script type="text/javascript" language="javascript">
//<![CDATA[
function CreateFixedHeaders() {}//]]>
</script>
<script>
var ClientReportfb64a4706a3749c484169e...
</script>
</body>
我最初的想法是用BeautifulSoup来去掉这些标签和属性。不过,我不能使用BeautifulSoup。既然BeautifulSoup不行,我想到有两个选项可以解决这个问题。第一个选项是把字符串拆分,然后根据索引来解析。这对我来说似乎不是个好办法。
另一个选项是使用正则表达式。不过,我们知道这也不是个好办法(Cthulhu解析)。
考虑到这些,我个人觉得用正则表达式来去掉属性是可以的。毕竟,这仍然是简单的字符串操作。
所以为了去掉属性,我有:
script_attribute_regex = r'\son[a-zA-Z]+="[a-zA-Z0-0\.;\(\)_]+"'
result = re.sub(script_attribute_regex, "", page_source)
正如我之前所说,我个人认为上面的正则表达式在处理HTML时是完全可以接受的。但我还是想听听大家对这种用法的看法。
接下来是关于脚本标签的问题。我很想用正则表达式来处理这个,因为我对它们很熟悉,而且我知道我需要的东西其实很简单。像这样:
<script(.*)</script>
上面的代码让我离我想要的结果更近了。是的,我知道上面的正则表达式会从第一个打开的脚本标签开始,一直到最后一个关闭的脚本标签,但这只是一个起始示例。
我很想用正则表达式,因为我对它们比较熟悉(比起Python更熟悉),而且我知道这是最快能得到我想要结果的方法,至少对我来说是这样。
所以我需要帮助,想要克服我的本性,不想走捷径。我想用正则表达式,但请有人指引我,带我走向不使用正则表达式的光明之路。
谢谢
更新:
看起来我没有很清楚地表达我的问题,抱歉。我想问的是,如何用纯Python解析HTML,而不使用正则表达式?
<script(.*)</script>
至于上面的代码示例,它是错误的。我知道它是错的,我只是用它作为一个起点的例子。
希望这能澄清我的问题
更新2
我想再补充一些关于我正在做的事情。
我正在爬取一个网站,以获取我需要的数据。
一旦我们获得了包含所需数据的页面,就会把它保存到数据库中。
然后保存的网页会展示给用户。
我想解决的问题发生在这里。当你尝试与该页面互动时,应用程序会抛出一个脚本错误,迫使用户点击一个确认框。这个应用程序不是一个网页浏览器,但使用了Windows中的网页浏览器DLL(我现在一时想不起来名字)。
这个错误只发生在这个特定网站的这一页上。
更新3
在添加更新后,我意识到我在过度思考这个问题,我在寻找一个更通用的解决方案。然而,在这种情况下,这并不是所需要的。
这个页面是动态生成的,但脚本标签是静态的。考虑到这一点,解决方案变得简单多了。因此,我不再需要把它当作HTML来处理,而是作为静态字符串。
所以我正在考虑的解决方案是
import re
def strip_script_tags(page_source: str) -> str:
pattern = re.compile(r'\s?on\w+="[^"]+"\s?')
result = re.sub(pattern, "", page_source)
pattern2 = re.compile(r'<script[\s\S]+?/script>')
result = re.sub(pattern2, "", result)
return result
我想避免使用正则表达式,不过,由于我只能使用标准库,正则表达式在这种情况下似乎是最好的解决方案。这意味着@skamazin的回答是正确的。
1 个回答
关于删除所有以 on
开头的属性,你可以试试 这个链接
它使用了正则表达式:
\s?on\w+="[^"]+"\s?
然后用空字符串替换(也就是删除)。所以在 Python 中应该是:
pattern = re.compile(ur'\s?on\w+="[^"]+"\s?')
subst = u""
result = re.sub(pattern, subst, file)
如果你想匹配脚本标签之间的内容,可以试试:
<script[\s\S]+?/script>
你正则表达式的问题在于那个点号 (.
) 不会匹配换行符。使用补充集合可以匹配所有可能的字符。而且要确保在 [\s\S]+?
中使用 ?
,这样它就会变得懒惰,而不是贪婪。