【问题标题】:BeautifulSoup: Strip specified attributes, but preserve the tag and its contentsBeautifulSoup:去除指定的属性,但保留标签及其内容
【发布时间】:2012-01-28 09:03:16
【问题描述】:

我正在尝试对 MS FrontPage 生成网站的 html 进行“defrontpagify”,并且正在编写一个 BeautifulSoup 脚本来执行此操作。

但是,我在尝试从包含它们的文档中的每个标记中去除特定属性(或列表属性)的部分上遇到了困难。代码sn-p:

REMOVE_ATTRIBUTES = ['lang','language','onmouseover','onmouseout','script','style','font',
                        'dir','face','size','color','style','class','width','height','hspace',
                        'border','valign','align','background','bgcolor','text','link','vlink',
                        'alink','cellpadding','cellspacing']

# remove all attributes in REMOVE_ATTRIBUTES from all tags, 
# but preserve the tag and its content. 
for attribute in REMOVE_ATTRIBUTES:
    for tag in soup.findAll(attribute=True):
        del(tag[attribute])

它运行没有错误,但实际上并没有去除任何属性。当我在没有外部循环的情况下运行它时,只需对单个属性进行硬编码(soup.findAll('style'=True),它就可以工作。

有人知道这里的问题吗?

PS - 我也不太喜欢嵌套循环。如果有人知道更实用的地图/过滤器风格,我很乐意看到它。

【问题讨论】:

  • 对我来说,如果将soup.findAll(attribute=True) 更改为简单的soup.findAll(),它就可以工作。
  • 不错,确实有效。事后看来很明显,不需要检查两次属性值。唯一的问题是它会检查文档中每个标签的所有属性,运行时间是原来的两倍,但 5 秒与 2.5 秒的约 15 个页面在这里没什么大不了的。

标签: python web-scraping beautifulsoup scraper frontpage


【解决方案1】:

线

for tag in soup.findAll(attribute=True):

没有找到任何tags。可能有一种方法可以使用findAll;我不确定。但是,这是可行的:

import BeautifulSoup
REMOVE_ATTRIBUTES = [
    'lang','language','onmouseover','onmouseout','script','style','font',
    'dir','face','size','color','style','class','width','height','hspace',
    'border','valign','align','background','bgcolor','text','link','vlink',
    'alink','cellpadding','cellspacing']

doc = '''<html><head><title>Page title</title></head><body><p id="firstpara" align="center">This is <i>paragraph</i> <a onmouseout="">one</a>.<p id="secondpara" align="blah">This is <i>paragraph</i> <b>two</b>.</html>'''
soup = BeautifulSoup.BeautifulSoup(doc)
for tag in soup.recursiveChildGenerator():
    try:
        tag.attrs = [(key,value) for key,value in tag.attrs
                     if key not in REMOVE_ATTRIBUTES]
    except AttributeError: 
        # 'NavigableString' object has no attribute 'attrs'
        pass
print(soup.prettify())

请注意,此代码仅适用于 Python 3。如果您需要它在 Python 2 中运行,请参阅下面 Nóra 的回答。

【讨论】:

  • 很好,谢谢!至于 findAll,我确定我只是以某种方式错误地引用了 attribute 变量,因为在其位置硬编码属性名称确实有效。在我让整个脚本正常工作后,将在下一次通过时深入研究。
【解决方案2】:

只是ftr:这里的问题是,如果您将HTML 属性作为关键字参数传递,关键字就是属性的name。因此,您的代码正在搜索名称为 attribute 的属性的标签,因为变量没有得到扩展。

这就是为什么

  1. 硬编码您的属性名称有效[0]
  2. 代码没有失败。搜索结果不匹配任何标签

要解决此问题,请将您要查找的属性作为dict 传递:

for attribute in REMOVE_ATTRIBUTES:
    for tag in soup.find_all(attrs={attribute: True}):
        del tag[attribute]

未来的某个人, dtk

[0]:虽然在您的示例中它需要是find_all(style=True),但没有引号,因为SyntaxError: keyword can't be an expression

【讨论】:

    【解决方案3】:

    我用这个方法去掉一个属性列表,很紧凑:

    attributes_to_del = ["style", "border", "rowspan", "colspan", "width", "height", 
                         "align", "valign", "color", "bgcolor", "cellspacing", 
                         "cellpadding", "onclick", "alt", "title"]
    for attr_del in attributes_to_del: 
        [s.attrs.pop(attr_del) for s in soup.find_all() if attr_del in s.attrs]
    
    
    

    【讨论】:

      【解决方案4】:

      这是一个 Python 2 版本的 unutbu 答案:

      REMOVE_ATTRIBUTES = ['lang','language','onmouseover']
      
      doc = '''<html><head><title>Page title</title></head><body><p id="firstpara" align="center">This is <i>paragraph</i> <a onmouseout="">one</a>.<p id="secondpara" align="blah">This is <i>paragraph</i> <b>two</b>.</html>'''
      
      soup = BeautifulSoup.BeautifulSoup(doc)
      
      for tag in soup.recursiveChildGenerator():
          if hasattr(tag, 'attrs'):
              tag.attrs = {key:value for key,value in tag.attrs.iteritems()
                          if key not in REMOVE_ATTRIBUTES}
      

      【讨论】:

        【解决方案5】:

        我用这个:

        if "align" in div.attrs:
            del div.attrs["align"]
        

        if "align" in div.attrs:
            div.attrs.pop("align")
        

        感谢https://stackoverflow.com/a/22497855/1907997

        【讨论】:

          猜你喜欢
          • 2010-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-12
          • 2013-03-24
          • 2020-10-20
          • 2019-09-23
          • 2015-02-20
          相关资源
          最近更新 更多