Извлечение текста из последовательности строк, заключенных в теги HTML, и строк без тегов - PullRequest
1 голос
/ 28 января 2020

Рассмотрим следующее HTML:

<li>
  <a href="url">
    <b>This</b>
    " is "
    <b>a</b>
    " test "
    <b>string</b>
    "!"
  </a>
</li>

Я бы хотел извлечь весь текст между тегом <a>, кроме "!". Другими словами, текст, содержащийся между первым открытием <b> и последним закрытием </b>: This is a test string.

from bs4 import BeautifulSoup

html = '''
<li>
<a href="url">
<b>This</b>
" is "
<b>a</b>
" test "
<b>string</b>
"!"
</a>
</li>
'''
soup = BeautifulSoup(html)
anchor = soup.a

Обратите внимание, что число тегов <b> и строк без тегов варьируется таким образом next или next_sibling не будет работать.

Есть ли более простой способ сделать это?

Редактировать: В идеале, я хотел бы, чтобы метод работал даже если у меня есть несколько строк, не заключенных в теги после последнего </b>.

Ответы [ 2 ]

2 голосов
/ 28 января 2020

Попробуйте код ниже

result = ''.join([i.strip().replace('"', '') for i in anchor.strings if i.strip()][:-1])
print(result)

вывод

'This is a test string'
1 голос
/ 28 января 2020

Исходя из ваших вопросов и комментариев, я думаю, что получение индексов подстрок и работа с целым подмножеством HTML может сделать то, что вам нужно.

Давайте создадим функцию для извлечения всех из индексов подстроки сначала (см. ответ @AkiRoss):

def findall(p, s):
    i = s.find(p)
    while i != -1:
        yield i
        i = s.find(p, i+1)

Затем используйте это, чтобы найти вхождения <b> и </b>.

opening_b_occurrences = [i for i in findall('<b>', html)]
# has the value of [21, 40, 58]
closing_b_occurrences = [i for i in findall('</b>', html)]
# has the value of [28, 44, 67]

Теперь вы можете использовать эту информацию, чтобы получить подстроку HTML для выполнения извлечения текста:

first_br = opening_b_occurrences[0]
last_br = closing_b_occurrences[-1] # getting the last one from list
text_inside_br = html[first_br:last_br]

Текст в text_inside_br теперь должен быть '<b>This</b>\n" is "\n<b>a</b>\n" test "\n<b>string'. Вы можете очистить его сейчас, например, добавив к нему </br> и используя BeautifulSoup для извлечения значений, или просто , используя для этого регулярное выражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...