15

我正在使用 BeautifulSoup 进行一些 HTML 清理。Python 和 BeautifulSoup 的新手。根据我在 Stackoverflow 其他地方找到的答案,我已经正确删除了标签,如下所示:

[s.extract() for s in soup('script')]

但是如何删除内联样式?例如以下:

<p class="author" id="author_id" name="author_name" style="color:red;">Text</p>
<img class="some_image" href="somewhere.com">

应该变成:

<p>Text</p>
<img href="somewhere.com">

如何删除所有元素的内联类、id、名称和样式属性?

其他类似问题的答案我可以找到所有提到的使用 CSS 解析器来处理这个问题,而不是 BeautifulSoup,但由于任务只是删除而不是操纵属性,并且是所有标签的一揽子规则,我希望找到一种在 BeautifulSoup 中完成这一切的方法。

4

6 回答 6

31

如果您只想将其全部删除,则无需解析任何 CSS。BeautifulSoup 提供了一种删除整个属性的方法,如下所示:

for tag in soup():
    for attribute in ["class", "id", "name", "style"]:
        del tag[attribute]

此外,如果您只想删除整个标签(及其内容),则不需要extract()返回标签。你只需要decompose()

[tag.decompose() for tag in soup("script")]

差别不大,只是我在查看文档时发现的其他内容。您可以在BeautifulSoup 文档中找到有关 API 的更多详细信息,其中包含许多示例。

于 2012-10-18T16:41:09.070 回答
11

我不会这样做BeautifulSoup——你会花费大量时间尝试、测试和解决边缘情况。

Bleach这正是为你做的。 http://pypi.python.org/pypi/bleach

如果您要在 中执行此操作BeautifulSoup,我建议您像这样Bleach做一样采用“白名单”方法。确定哪些标签可能具有哪些属性,并删除每个不匹配的标签/属性。

于 2012-10-18T16:47:10.200 回答
3

这是我对 Python3 和 BeautifulSoup4 的解决方案:

def remove_attrs(soup, whitelist=tuple()):
    for tag in soup.findAll(True):
        for attr in [attr for attr in tag.attrs if attr not in whitelist]:
            del tag[attr]
    return soup

它支持应保留的属性白名单。:) 如果没有提供白名单,所有属性都会被删除。

于 2016-04-01T13:19:23.997 回答
1

基于 jmk 的功能,我使用此功能删除基于白名单的属性:

在 python2、BeautifulSoup3 中工作

def clean(tag,whitelist=[]):
    tag.attrs = None
    for e in tag.findAll(True):
        for attribute in e.attrs:
            if attribute[0] not in whitelist:
                del e[attribute[0]]
        #e.attrs = None     #delte all attributes
    return tag

#example to keep only title and href
clean(soup,["title","href"])
于 2013-07-26T21:33:24.283 回答
1

lxml 的 Cleaner 呢?

from lxml.html.clean import Cleaner

content_without_styles = Cleaner(style=True).clean_html(content)
于 2021-04-20T07:49:43.287 回答
0

不完美但简短:

' '.join([el.text for tag in soup for el in tag.findAllNext(whitelist)]);
于 2019-06-12T10:13:01.183 回答