BeautifulSoup: удалите указанные атрибуты, но сохраните тег и его содержимое

Я пытаюсь "defrontpagify" html веб-сайта, созданного MS FrontPage, и я пишу сценарий 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']

# 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])

он выполняется без ошибок, но на самом деле не все атрибуты. Когда я запускаю его без внешнего цикла, просто жестко кодирую один атрибут (суп.findAll ('style' =True), он работает.

кто-нибудь видит здесь проблему?

PS-мне тоже не очень нравятся вложенные циклы. Если кто-нибудь знает более функциональный стиль карты/фильтра, я бы хотел его увидеть.

3 ответов


строку

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())

Я использую BeautifulSoup 4 С python 2.7 и для меня tag.attrs - это словарь, а не список. Поэтому мне пришлось изменить этот код:

    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}

просто 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]

Hth кто-то в будущем, dtk

[0]: хотя это должно быть find_all(style=True) в вашем примере, без кавычек, потому что SyntaxError: keyword can't be an expression