BeautifulSoup: ошибка атрибута: объект ‘NavigableString’ не имеет атрибута ‘name’

#python #beautifulsoup

#python #beautifulsoup

Вопрос:

Знаете ли вы, почему первый пример в учебнике BeautifulSoup http://www.crummy.com/software/BeautifulSoup/documentation.html#QuickStart дает AttributeError: 'NavigableString' object has no attribute 'name' ? Согласно этому ответу, проблема возникает из-за пробелов в HTML. Я попробовал с источниками нескольких страниц, и 1 сработал, остальные выдали ту же ошибку (я удалил пробелы). Можете ли вы объяснить, что означает «name» и почему возникает эта ошибка? Спасибо.

Ответ №1:

Просто игнорируйте NavigableString объекты во время итерации по дереву:

 from bs4 import BeautifulSoup, NavigableString, Tag

response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')

for body_child in soup.body.children:
    if isinstance(body_child, NavigableString):
        continue
    if isinstance(body_child, Tag):
        print(body_child.name)
  

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

1. Потрясающе! Работает как шарм в 2021 году! Спасибо, Макс! 🙂

2. ты мужчина. спасибо!

Ответ №2:

name будет ссылаться на имя тега, если объект является Tag объектом (т.е.: <html> name = «html»)

если в вашей разметке между узлами есть пробелы, BeautifulSoup превратит их в NavigableString «s». Поэтому, если вы используете индекс contents для захвата узлов, вы можете захватить a NavigableString вместо следующего Tag .

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

или, если вы знаете имя следующего нужного тега, вы можете использовать это имя в качестве свойства, и оно вернет первое Tag с этим именем, или None если дочерних элементов с таким именем не существует: использование имен тегов в качестве членов

Если вы хотите использовать contents , вам нужно проверить объекты, с которыми вы работаете. Ошибка, которую вы получаете, просто означает, что вы пытаетесь получить доступ к свойству name, потому что код предполагает, что это Tag

Ответ №3:

Вы можете использовать try catch, чтобы исключить случаи, когда навигационная строка анализируется в цикле, например:

     for j in soup.find_all(...)
        try:
            print j.find(...)
        except NavigableString: 
            pass
  

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

1. Я получил: кроме NavigableString: ошибка типа: при использовании этого не допускается перехват классов, которые не наследуются от BaseException

2. Вместо try / catch, возможно NavigableString , более полезно тестирование экземпляра (поскольку try / catch работает только для классов, унаследованных от классов исключений): python for child in date.children: if isinstance(child, NavigableString): text = child.strip() else: text = child.text.strip()

Ответ №4:

Это последний рабочий код для получения имени тегов в soup.

 from bs4 import BeautifulSoup, Tag

res = requests.get(url).content
soup = BeautifulSoup(res, 'lxml')

for child in soup.body.children:
    if isinstance(body_child, Tag):
        print(child.name)