首页 > 解决方案 > 使用 BeautifulSoup 解析时如何考虑元素的祖先?

问题描述

我正在使用 Python 3.7、Django 和 BeautifulSoup。我目前正在我的文档中寻找包含文本“Review”的“span”元素。我这样做

html = urllib2.urlopen(req, timeout=settings.SOCKET_TIMEOUT_IN_SECONDS).read()

my_soup = BeautifulSoup(html, features="html.parser")

rev_elts = my_soup.findAll("span", text=re.compile("Review"))
for rev_elt in rev_elts:
    ... processing

但是我想在我不想考虑这些元素的地方添加一个皱纹,如果它们有一个带有“子”类的 DIV 祖先。例如,我不想考虑这样的事情

    <div class="child">
        <p>
            <span class="s">Reviews</span>
        ...
    </p>
</div>

我如何调整我的搜索以考虑到这一点?

标签: djangopython-3.xparsingbeautifulsoup

解决方案


正如@facelessuser 所回答的那样,CSS 选择器是在这种情况下要走的路。但是以防万一您想知道这也可以在不使用 css 选择器的情况下完成。

您可以使用.parents遍历元素的所有父级。您可以定义一个自定义过滤器函数,该函数检查是否有任何父母具有“孩子”类,否则返回True(除了所有其他条件)。

from bs4 import BeautifulSoup, Tag
html="""
<div class="child">
<p><span id="1">Review</span></p>
</div>
<div>
<p><span id="2">Review</span></p>
</div>
"""
soup=BeautifulSoup(html,'html.parser')
def my_func(item):
    if isinstance(item,Tag) and item.name=='span' and 'Review' in item.text:
        for parent in item.parents:
            if parent.has_attr('class'):
                if 'child' in parent.get('class'):
                    return False
        return True
my_spans=soup.find_all(my_func)
print(my_spans)

输出:

[<span id="2">Review</span>]

推荐阅读