Использование BeautifulSoup для извлечения текста в промежутках между двумя заголовками

Я пытаюсь использовать BeautifulSoup для извлечения текста из гида по концертам со списками по жанрам. Я совершенно новичок в этом, и я обнаружил, что могу вернуть список жанров и полный список названий концертов, но, конечно, я хочу вернуть только названия концертов, связанные с определенным жанром (и затем перейти к следующий жанр и выбрать его названия концертов и т. д.) Исходный код руководства по концертам выглядит следующим образом:

<h3>indie</h3>
    <span class="gig-title"><a href="/gig/BandA">BandA</a></span> 
    <span class="gig-title"><a href="/gig/BandB">BandB</a></span> 
    <span class="gig-title"><a href="/gig/BandC">BandC</a></span> 

<h3>jazz</h3>
    <span class="gig-title"><a href="/gig/BandD">BandD</a></span> 
    <span class="gig-title"><a href="/gig/BandE">BandE</a></span>

Я могу найти все жанры и названия концертов примерно так:

genres = soup.find_all("h3")
for genre in genres:
    titles = soup.find_all("span","gig-title")
    for title in titles:
        gig = title.a.string

Но я просто хочу вернуть текст: "BandA", "BandB", "BandC" - это текст между двумя тегами h3 (жанр), прежде чем перейти к следующему жанру.

Как я могу подойти к этой проблеме?


person rhop    schedule 29.05.2017    source источник


Ответы (1)


Вы можете использовать findall() для одновременного поиска заголовка и данных. А затем просто работайте с той частью данных, которая вам нужна:

Код:

def get_genre_band(soup):
    genre = None
    for node in soup.findAll(['h3', 'span']):
        if node.name == 'h3':
            genre = node.text
        elif 'gig-title' in node.get('class', ''):
            yield genre, node.text

Тестовый код:

data = """
    <h3>indie</h3>
        <span class="gig-title"><a href="/gig/BandA">BandA</a></span> 
        <span class="gig-title"><a href="/gig/BandB">BandB</a></span> 
        <span class="gig-title"><a href="/gig/BandC">BandC</a></span> 

    <h3>jazz</h3>
        <span class="gig-title"><a href="/gig/BandD">BandD</a></span> 
        <span class="gig-title"><a href="/gig/BandE">BandE</a></span>
"""

from bs4 import BeautifulSoup
for g, b in get_genre_band(BeautifulSoup(data, 'lxml')):
    print("{} {}".format(g, b))

Полученные результаты:

indie BandA
indie BandB
indie BandC
jazz BandD
jazz BandE
person Stephen Rauch    schedule 29.05.2017
comment
Спасибо! Я обнаружил, что это работает, если я использую данные примера, но когда я действительно открываю веб-страницу, чтобы использовать данные, я получаю сообщение об ошибке для следующей строки: elif 'gig-title' в узле ['класс']: я могу избавиться от этой ошибки, если я редактирую ['класс'] на (['класс']) или ('класс'), но тогда ничего не происходит. (Обратите внимание, что я использую BeautifulSoup(data, 'html.parser'), а не 'lxml' - не уверен, может ли это быть частью проблемы?) - person rhop; 29.05.2017
comment
Спасибо за обновление - это круто. Теперь, чтобы перейти к следующей проблеме! - person rhop; 31.05.2017