Как спарсить текст из тега, вложенного в другой тег с помощью BS4

Рейтинг: 0Ответов: 1Опубликовано: 27.06.2023

Задача состоит в том, чтобы спарсить карточку товара с сайта https://vedro.pro/oils_catalog?viewMode=tile&goods_group=oils&start=0. При работе у меня возникло несколько проблем:

  1. Не получается взять из карточки описание из двух тегов p и a. Так как тег а вложен в тег р, у меня не выходит вытащить текст.
  2. Не получается спарсить карточки с других страниц, т.е. при попытки парсинга товаров со второй страницы в консоль все равно выводятся названия товаров с первой, и т.д. На мой взгляд, я правильно прописал цикл так, чтобы он подставлял в ссылку число, соответствующее ссылке страницы.

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

Вот код, который я накидал:

import requests
from bs4 import BeautifulSoup
from time import sleep


headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac), Apple Inc (US) 
AppleWebKit/537.36 (KHTML, like Ge)'}


for count in range(0, 180, 20):
    url = f'https://vedro.pro/oils_catalog?viewMode=tile&goods_group=oils&start={count}'

    response = requests.get(url, headers=headers, params=None)
    soup = BeautifulSoup(response.text, 'lxml')
    data = soup.find('ul', class_='item_ul')

    for i, el in enumerate(data):
        for j in data.find_all('p'):
            name = data.find_all('h3')
            print('-' * 20 + '\n',
                  name[i].text.strip() + '\n',
                  f'{j.text.strip()}' + '\n' +
                  '-' * 20)

        sleep(5)

Ответы

▲ 1Принят

Если я правильно понял, то вы пытаетесь получить название масел. Как вариант это можно сделать так:

soup = BeautifulSoup(html_text, 'lxml') # в html_text код страницы

# ищем все ul с классом item_ul и перебираем
for el_ul in soup.findAll('ul', attrs = {'class':'item_ul'}):

    # перебираем найденные ul и ищем в них тег а с классом brandInfoLink
    for el_a in el_ul.findAll ('a', attrs = {'class':'brandInfoLink'}): 

        # перебираем все найденный а и выводим содержимое и параметры (тут ссылка) при необходимости
        name = el_a.text.strip()
        print (f'Название: {name} Ссылка: {el_a["href"]}')

Выводом будет:

Название: Hyundai-KIA Ссылка: https://vedro.pro/oils_catalog?viewMode=tile&goods_group=oils&start=0#
Название: LUKOIL Ссылка: https://vedro.pro/oils_catalog?viewMode=tile&goods_group=oils&start=0#
Название: GENERAL MOTORS Ссылка: https://vedro.pro/oils_catalog?viewMode=tile&goods_group=oils&start=0#
Название: NISSAN Ссылка: https://vedro.pro/oils_catalog?viewMode=tile&goods_group=oils&start=0#

Стоит отметить, что не обязательно перемещаться по всему дереву элемент за элементом, просто укажите в каком элементе вы собираетесь что-то искать.

Если нужно бонусом вытащить еще и дополнительные атрибуты товара, то возможно сделать так:

soup = BeautifulSoup(html_text, 'lxml')
for el_li in soup.findAll('li', attrs = {'class':'item'}):
    print (f"Название: {el_li.find ('a', attrs = {'class':'brandInfoLink'}).text.strip()}")
    # перебираем все td в li
    for el_td in el_li.findAll ('td'):
        print (el_td.text.strip())

Выводом для такого кода будет:

Название: Hyundai-KIA
PP481
2 - 4 дня
> 100
3 370 руб.

Стоит обратить внимание, что в этом случае поиск осуществляется по тегу li, а не ul. Так же, если есть доступно несколько складов, то они будут выведены под названием друг за другом.