从HTML中移除脚本标签和on属性

4 投票
1 回答
3813 浏览
提问于 2025-04-18 15:56

我有一段HTML代码,我需要把里面的脚本标签和任何与脚本相关的属性去掉。这里说的与脚本相关的属性是指那些以“on”开头的属性。

<body>
<script src="...">

    </script>
<div onresize="CreateFixedHeaders()" onscroll="CreateFixedHeaders()" id="oReportDiv" style="overflow:auto;WIDTH:100%">

<script type="text/javascript" language="javascript">

//&lt;![CDATA[

function CreateFixedHeaders() {}//]]&gt;
</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 个回答

4

关于删除所有以 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]+? 中使用 ?,这样它就会变得懒惰,而不是贪婪。

撰写回答