首页 > 解决方案 > BeautifulSoup 获取与类最近的标签,而不是兄弟姐妹并嵌套在未知兄弟姐妹中

问题描述

<h3>
    <span></span>
    <span class='headline'>Headline #1</span>
</h3>
<table class='striped'></table>
<h4>
    <span class='headline'>Headline #2</span>
</h4>
<table class='striped'></table>
<p>
    <span class='headline'>Headline #3</span>
</p>
<ul></ul>
<center>
    <table class='striped'></table>
</center>

这是我的结构。我正在枚举表格标签,并希望使用最接近我的表格的“标题”类检索跨度标签的文本值。“最近”的意思是,如果您要展平 html,我想使用一个类“标题”来定位跨度,如果您从表格的起点开始,您会首先遇到它

有时这些跨度嵌套在 h3 中,有时是 h4,有时是 ap 标签。有时 table 标记与 h3/h4/p 处于同一级别,有时它本身嵌套在 center 标记内。有时 h3/h4/p 标签是表的直接兄弟,有时不是。

如何使用 BeautifulSoup 找到最近的 span.headline 而不管嵌套级别如何,以及它是否嵌套在父级或兄弟级中?

到目前为止,我已经得到了这个代码

tables = soup.findAll("table", {"class": ["striped"]})

for index, table in enumerate(tables):
    headline = table.find_previous('h3').("span", {"class" : ["headline"]}).text

标签: pythonbeautifulsoup

解决方案


I was able to use the find_previous method on each table to find the previous headline for the sample html you provided. I added an additional idx attribute to each table to use when checking if the headline belongs to that table. I also added two tables to the beginning and end of the html that have no previous headline.

html = '''
<table class='striped'></table>
<h3>
    <span></span>
    <span class='headline'>Headline #1</span>
</h3>
<table class='striped'></table>
<h4>
    <span class='headline'>Headline #2</span>
</h4>
<table class='striped'></table>
<p>
    <span class='headline'>Headline #3</span>
</p>
<ul></ul>
<center>
    <table class='striped'></table>
</center>
<table class='striped'></table>
</div>
'''.replace('\n', '')

soup = BeautifulSoup(html, 'lxml')
table_query = ('table', {'class': 'striped'})
headline_query = ('span', {'class': 'headline'})

for idx, table in enumerate(soup.find_all(*table_query)):
    table.attrs['idx'] = idx
    previous_headline = table.find_previous(*headline_query)
    if (previous_headline and 
        previous_headline.find_next(*table_query).attrs['idx'] == idx):
        print(previous_headline.text)
    else:
        print('No headline found.')

Output:

No headline found.
Headline #1
Headline #2
Headline #3
No headline found.

推荐阅读