Ошибка атрибута BeautifulStoneSoup: объект ‘NavigableString’ не имеет атрибута ‘subtag’

#python #xml #beautifulsoup

#python #xml #beautifulsoup

Вопрос:

Я пытаюсь использовать BeautifulSoup для анализа некоторого XML, который выглядит как

 <a>
  <b>
    <c>
      <d attr="x">
        <e>
        </e>
        <name>
        </name>
      </d>
    </c>
    <c>
      ...
    <c>
  </b>
</a>
  

но я не могу понять, как получить доступ к e or name в цикле. Это работает:

 print soup.a.b.c.d.e
  

но это не:

 for subtag in soup.a.b.c:
    print subtag.d.e
  

вместо этого он выдает эту ошибку:

 AttributeError: 'NavigableString' object has no attribute 'd'
  

и, что несколько не связано, это:

 print soup.a.b.c.d.name
  

только выходные данные d .

Что я делаю не так? Я подозреваю, что для второй проблемы мне придется использовать find() вместо этого, потому что у этого объекта уже есть name атрибут. Есть ли более приятный способ?

Комментарии:

1. Какова цель этого синтаксического анализа? Вы привязываетесь к извлечению первого e элемента каждого d элемента, содержащегося в первом a.b.c элементе?

2. Я хочу, чтобы все ( d , e , name ) группы.

Ответ №1:

Вы получаете, AttributeError потому что BSS возвращает NavigableString s при циклическом переборе Tag экземпляров. Может быть, вы хотите попробовать:

 soup.a.b.c.findChildren()
#[<d attr="x">
#<e>
#</e>
#<name>
#</name>
#</d>, <e>
#</e>, <name>
#</name>]
  

Что касается проблемы с name : она указана как атрибут, но вместо этого вы можете сделать:

 soup.a.b.c.d.findChildren('name')
#[<name>
#</name>]
  

Установочный код для справки:

 from BeautifulSoup import BeautifulStoneSoup as bss
soup = bss(markup)
  

Ответ №2:

это:

 print soup.a.b.c.d.name
  

выводит только d.

Это происходит потому, что name конфликтует со встроенным name атрибутом объектов тегов. Согласно документации по использованию имен тегов в качестве членов, вы можете использовать soup.a.b.c.d.nameTag вместо этого.

Ошибка атрибута хорошо объяснена в других ответах. Если вы хотите извлечь каждую (d, e, name) тройку во всем документе, независимо от того, где появляется d тег, вы могли бы сделать что-то вроде этого:

 soup = BeautifulStoneSoup(doc)
for d in soup.findAll('d'):
    print (d, d.e, d.nameTag)