Использование BeautifulSoup для извлечения текста между разрывами строк (например, теги ‹br /›)

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

<br />
Important Text 1
<br />
<br />
Not Important Text
<br />
Important Text 2
<br />
Important Text 3
<br />
<br />
Non Important Text
<br />
Important Text 4
<br />

В настоящее время я использую BeautifulSoup для получения других элементов в HTML, но мне не удалось найти способ получить важные строки текста между тегами <br />. Я могу изолировать и перейти к каждому из элементов <br />, но не могу найти способ получить текст между ними. Любая помощь будет принята с благодарностью. Спасибо.


person maltman    schedule 11.03.2011    source источник


Ответы (4)


Если вам просто нужен любой текст, который находится между двумя тегами <br />, вы можете сделать что-то вроде следующего:

from BeautifulSoup import BeautifulSoup, NavigableString, Tag

input = '''<br />
Important Text 1
<br />
<br />
Not Important Text
<br />
Important Text 2
<br />
Important Text 3
<br />
<br />
Non Important Text
<br />
Important Text 4
<br />'''

soup = BeautifulSoup(input)

for br in soup.findAll('br'):
    next_s = br.nextSibling
    if not (next_s and isinstance(next_s,NavigableString)):
        continue
    next2_s = next_s.nextSibling
    if next2_s and isinstance(next2_s,Tag) and next2_s.name == 'br':
        text = str(next_s).strip()
        if text:
            print "Found:", next_s

Но, может быть, я неправильно понял ваш вопрос? Ваше описание проблемы, похоже, не совпадает с «важным» / «неважным» в данных вашего примера, поэтому я пошел с описанием;)

person Mark Longair    schedule 11.03.2011
comment
Ааа, проблема была в том, что я использовал findNextSibling(), и это просто пропускало текст и переходило к следующему разрыву строки. Использование nextSibling сработало. Спасибо за помощь! - person maltman; 14.03.2011
comment
Отличный ответ, это спасло меня от головной боли! - person Nick; 24.07.2013
comment
Разве next не является зарезервированным словом в Python? Возможно, было бы лучше использовать другое имя переменной? (Это мелочь, но такие вещи складываются!) - person duhaime; 18.10.2013
comment
duhaime: на самом деле это не ключевое слово в Python (continue является Python-эквивалентом next в других языках) - person Mark Longair; 18.10.2013
comment
Марк, это сработало нормально, ЗА ИСКЛЮЧЕНИЕМ, он вернул текст 2 через n. Я все еще пытаюсь получить первый текст, который ЗАКАНЧИВАЕТСЯ на ‹br/› - person Brian L Cartwright; 01.02.2014
comment
@MarkLongair next может не быть «ключевым словом», таким как for или if, но это встроенная функция, и она будет переназначена в приведенной выше реализации. Таким образом, продвижение итератора с использованием my_val = next(my_generator) завершится ошибкой после переназначения. Использование next в качестве имени переменной IMO нецелесообразно. docs.python.org/2/library/functions.html#next - person André C. Andersen; 09.04.2017
comment
@André Christoffer Andersen: конечно, да, хорошая мысль! Я изменил это в ответе, чтобы он не затенял встроенную функцию. - person Mark Longair; 10.04.2017

Итак, в целях тестирования предположим, что этот фрагмент HTML находится внутри тега span:

x = """<span><br />
Important Text 1
<br />
<br />
Not Important Text
<br />
Important Text 2
<br />
Important Text 3
<br />
<br />
Non Important Text
<br />
Important Text 4
<br /></span>"""

Теперь я собираюсь разобрать его и найти свой тег span:

from BeautifulSoup import BeautifulSoup
y = soup.find('span')

Если вы повторите генератор в y.childGenerator(), вы получите как br, так и текст:

In [4]: for a in y.childGenerator(): print type(a), str(a)
   ....: 
<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 
Important Text 1

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 
Not Important Text

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 
Important Text 2

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 
Important Text 3

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 
Non Important Text

<type 'instance'> <br />
<class 'BeautifulSoup.NavigableString'> 
Important Text 4

<type 'instance'> <br />
person Ken Kinder    schedule 11.03.2011

Для меня работало следующее:

for br in soup.findAll('br'):
    if str(type(br.contents[0])) == '<class \'BeautifulSoup.NavigableString\'>':
       print br.contents[0]
person Pontios    schedule 02.02.2016
comment
Пожалуйста, не полагайтесь на строковое представление объектов для логики вашего кода. - person Sylvain; 05.05.2017

Небольшое улучшение ответа Кена Киндера. Вместо этого вы можете получить доступ к атрибуту stripped_strings элемента BeautifulSoup. Например, предположим, что ваш конкретный фрагмент HTML находится внутри тега span:


x = """<span><br />
Important Text 1
<br />
<br />
Not Important Text
<br />
Important Text 2
<br />
Important Text 3
<br />
<br />
Non Important Text
<br />
Important Text 4
<br /></span>"""

Сначала мы разбираем x с помощью BeautifulSoup. Затем найдите элемент, в данном случае span, а затем получите доступ к атрибуту stripped_strings. Вот так,

from bs4 import BeautifulSoup
soup = BeautifulSoup(x)
span = soup.find("span")
text = list(span.stripped_strings)

Теперь print(text) выдаст следующий результат:

['Important Text 1',
 'Not Important Text',
 'Important Text 2',
 'Important Text 3',
 'Non Important Text',
 'Important Text 4']
person Devendra Damle    schedule 30.06.2021
comment
Я получаю, что объект «список» не вызывается для этого - person rearThing; 09.07.2021