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