BeautifulSoup find - исключить вложенный тег из интересующего блока - PullRequest
0 голосов
/ 17 октября 2018

У меня есть скребок, который ищет цены на определенных страницах продукта.Меня интересует только текущая цена - продается продукт или нет.

Я сохраняю идентифицирующие теги, подобные этой, в файле JSON:

{
    "some_ecommerce_site" : {
        "product_name" : ["span", "data-test", "product-name"],
        "breadcrumb" : ["div", "class", "breadcrumbs"],
        "sale_price" : ["span", "data-test", "sale-price"],
        "regular_price" : ["span", "data-test", "product-price"]
    },
}

И у меня есть эти функциичтобы выбрать текущую цену и очистить текст цены:

def get_pricing(rpi, spi):
    sale_price = self.soup_object.find(spi[0], {spi[1] : spi[2]})
    regular_price = self.soup_object.find(rpi[0], {rpi[1] : rpi[2]})

    return sale_price if sale_price else regular_price

def get_text(obj):
    return re.sub(r'\s\s+', '', obj.text.strip()).encode('utf-8')

Которые называются:

def get_ids(name_of_ecommerce_site):
    with open('site_identifiers.json') as j:
        return json.load(j)[name_of_ecommerce_site]

def get_data():
    rpi = self.site_ids['regular_price']
    spi = self.site_ids['sale_price']

    product_price = self.get_text( self.get_pricing(rpi, spi) )

Пока это работает для всех сайтов, кроме одного, потому что их цены отформатированы следующим образом:

<div class="product-price">
    <h3>
    £15.00
        <span class="price-standard">
            £35.00
        </span>
    </h3>
</div>

Так что product_price возвращает "£ 15 £ 35" вместо желаемого "£ 15".

Есть ли простой способ исключить вложенный <span>что не сломается для рабочих сайтов?

Я думал, что решением было бы получить список и выбрать индекс 0, но при проверке содержимого тега это не сработает, так как это единственный элемент в списке:

>> print(type(regular_price))
>> <class 'bs4.element.Tag'> 
>> print(regular_price.contents)
>> [u'\n', <h3>\n\n\xa325.00\n\n<span class="price-standard">\n\n\xa341.00\n</span>\n</h3>, u'\n']

Я попытался создать список из элементов NavigableString результата, а затем отфильтровать пустые строки:

filter(None, [self.get_text(unicode(x)) for x in sale_price.find_all(text=True)])

Это исправляет один случай, но разбивает несколько других (поскольку они часто имеют валюту втег, отличный от суммы значения) - я получаю обратно "£".

1 Ответ

0 голосов
/ 18 октября 2018

Если вы хотите получить текст без дочернего элемента one.You может сделать это

from bs4 import BeautifulSoup,NavigableString


html = """
<div class="product-price">
    <h3>
    £15.00
        <span class="price-standard">
            £35.00
        </span>
    </h3>
</div>
"""
bs = BeautifulSoup(html,"xml")
result = bs.find("div",{"class":"product-price"})
fr = [element for element in result.h3 if isinstance(element, NavigableString)]
print(fr[0])

вопрос может быть дубликатом это

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...