首页 > 解决方案 > BeautifulSoup 查找 - 从感兴趣的块中排除嵌套标签

问题描述

我有一个在特定产品页面上查找定价的刮板。我只对当前价格感兴趣——产品是否在销售。

我将这样的识别标签存储在 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)])

这解决了一种情况,但打破了其他一些情况(因为他们经常将货币置于与价值金额不同的标签中) - 我得到“£”。

标签: pythonbeautifulsoupnested

解决方案


如果你想得到没有子元素的文本。你可以这样做

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

问题可能与此重复


推荐阅读