Задать вопрос
@66656665
22 года

Почему парсер выдает ошибку?

Смотрите, мне необходимо применить find_all в find. Как это сделать, можно ли вообще?
Вот код:
def get_content(html):
    soup = BeautifulSoup(html, 'html.parser')
    items = soup.find_all('li', class_='hor-menu__item has-subm')
    tovari = []

    for item in items:
        tovari.append(
            {
            'karegoria': item.find('a', class_='hor-menu__lnk').find('span', class_='hor-menu__text').get_text(),
            'podkategoria': item.find('div', class_='hor-menu__submenu mega').find('div', class_='mega-m').find('ul', class_='mega-m__inner').find_all('li', class_='mega-m__item').find('div', class_='menu-categ').find('div', class_='menu-categ__header').find('a', class_='menu-categ__title').find('div', class_='menu-categ__title-text').get_text()


            }

   )
    return tovari

html = get_html(URL)
print(get_content(html.text))


Вот ошибка:
Traceback (most recent call last):
File "C:/Users/Я/AppData/Local/Programs/Python/Python38-32/gg.py", line 36, in
print(get_content(html.text))
File "C:/Users/Я/AppData/Local/Programs/Python/Python38-32/gg.py", line 27, in get_content
'podkategoria': item.find('div', class_='hor-menu__submenu mega').find('div', class_='mega-m').find('ul', class_='mega-m__inner').find_all('li', class_='mega-m__item').find('div', class_='menu-categ').find('div', class_='menu-categ__header').find('a', class_='menu-categ__title').find('div', class_='menu-categ__title-text').get_text()
File "C:\Users\Я\AppData\Local\Programs\Python\Python38-32\lib\site-packages\bs4\element.py", line 2173, in __getattr__
raise AttributeError(
AttributeError: ResultSet object has no attribute 'find'. You're probably treating a list of elements like a single element. Did you call find_all() when you meant to call find()?
>>>
  • Вопрос задан
  • 425 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
@o5a
find_all возвращает список найденных значений, поэтому нельзя напрямую к нему по цепочке применять find. Проще всего изменить до рабочего варианта, используя list comprehension (используя Ваш же синтаксис):

'podkategoria': [item.find('div', class_='menu-categ').find('div', class_='menu-categ__header').find('a', class_='menu-categ__title').find('div', class_='menu-categ__title-text').get_text() for item in item.find('div', class_='hor-menu__submenu mega').find('div', class_='mega-m').find('ul', class_='mega-m__inner').find_all('li', class_='mega-m__item')]


Т.е. формируем список из результатов find_all.

Кстати, вместо цепочки find.find ... можно использовать select (синтаксис можно найти в документации, там записывается цепочка тэгов). Ищет аналогично, но выглядит более компактно и читабельно. В данном случае это бы выглядело так:

'podkategoria': [p.text for p in item.select('div.hor-menu__submenu.mega div.mega-m ul.mega-m__inner li.mega-m__item div.menu-categ div.menu-categ__header a.menu-categ__title div.menu-categ__title-text')]


И еще по структуре выгрузки, может логичнее ее сделать так, чтобы выгружался не список словарей по категориям, а сразу словарь вида {категория: список_подкатегорий}, чтобы выглядело так

{'НОВИНКИ': ['НОВИНКИ НИГМА', 'НОВИНКИ МАХАОН', ...], 'КНИГИ': ['ИД Мещеряков', 'ЭКСМО', 'АСТ' ... }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
5fa43b265255b076231817.png
Ответ написан
Комментировать
@GLEF1X
Ты неправильно делаешь парсинг в словаре, нельзя вызывать 2 функции find. Ты должен выбрать всё из базового класа, и оттуда получить через функцию find определенные значения и иерархию строить совсем необязательно.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы