BS Извлечь весь текст между двумя указанными ключевыми словами

С Python и BS мне нужно извлечь весь текст, содержащийся между двумя указанными словами

блабла текст мне нужен блибли

Мне удалось извлечь внутри DIV и TAG, но не для конкретного и другого ключевого слова.

спасибо за помощь

Пожалуйста, приведите пример, где это работает, и тот, где это не так.

muzzletov 03.04.2023 00:30

Звучит как задача для регулярного выражения, что bs4

Driftr95 03.04.2023 07:29
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
66
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Предполагая, что вы извлекли все слова между указанным тегом, теперь у вас есть строка, извлеченная в хронологическом порядке, в соответствии с тем, как был написан текст...

Получив полную текстовую строку, вы можете получить подстроку между двумя разными словами, каждое из которых встречается в тексте только один раз:

text = {text}
def get_textchunk(word1, word2, text):
        new_text = text.split(word1)
        new_text = new_text[1]
        newnew_text = new_text.split(word2)
        return newnew_text
print(get_textchunk('word1','word2',text)[0])

Это функция, которая будет разделена на два этапа с использованием двух разных слов.

Если вы хотите получить текст между двумя одинаковыми словами, которые встречаются только дважды (один раз в начале текста и один раз в конце), используйте этот код:

def get_textchunk(word, text):
        text = text.split(word)
        return text
print(get_textchunk('word', text)[1])

Это даст вам середину текста, который вы только что разделили.

Если вы хотите получить текст между двумя разными словами, которые часто встречаются в тексте, используйте этот код:

def get_textchunk(word1, word2, text):
        idx1 = text.index(word1)
        idx2 = text.index(word2)
        for idx in range(idx1 + len(word1) + 1, idx2):
                new_text = new_text + text[idx]
        return new_text

Эта функция может быть наиболее полезной для вас.

Настраивать:
# from bs4 import BeautifulSoup
# htmlStr = response.text ## if you're fetching with a request
htmlStr = '''
<div>
    <h3>Some Section</h3>
    Some text from Section 1

    <h3> Contact </h3>
    Adresse : Address Line One <br/> Address Line Two <br/>
    Téléphone : 0X XX XX XX XX <br/> 
    Site : <a href = "https://example.com/">https://example.com/</a>

    <h3>Some Other Section</h3>
    field 1 : some info 
    field 2 : __ <br/> field 3 : some other info
</div>
'''

soup = BeautifulSoup(htmlStr, 'lxml')



Получение всей информации в разделе

def get_section_info(section_header):
    hName, hList = section_header.name, 'h1,h2,h3,h4,h5,h6'
    hList = [h for h in hList.split(hName)[0].split(',') if h] + [hName]

    section_info, cur_key = {}, None
    for ns in section_header.next_siblings:
        if ns.name in hList: break ## stop if you reach the next section
        if not ((isinstance(ns,str) and not ns.PREFIX) or ns.name): continue ## skip

        nsStr = ' '.join((ns if isinstance(ns,str) else ns.get_text(' ')).split())
        if ':' in nsStr and not nsStr.startswith('http'): 
            cur_key, nsStr = [s.strip() for s in nsStr.split(':',1)]

        ckStr = section_info.get(cur_key, '')
        if ns.name == 'br': section_info[cur_key] = ckStr + ' \n'
        elif nsStr: section_info[cur_key] = ckStr + ' ' + nsStr
    
    section_info = {k:v.strip() for k,v in section_info.items()}
    return section_info[None] if [*section_info]==[None] else section_info

Это может выглядеть излишне запутанно, но вы можете получить всю контактную информацию с помощью

if (contact_h3 := soup.find('h3', string=lambda s: s and s.strip()=='Contact')):
    contact_info = get_section_info(contact_h3)
else: contact_info, _ = {}, print('Could not find <h3>Contact</h3>')

и contact_info будет выглядеть

{ 'Adresse': 'Address Line One \n Address Line Two', 
  'Téléphone': '0X XX XX XX XX', 
  'Site': 'https://example.com/' }

Вы даже можете получить все разделы h3 так же просто, как

{h3.text.strip(): get_section_info(h3) for h3 in soup.select('h3')}

который бы вернулся

{
  'Some Section': 'Some text from Section 1',
  'Contact': {
    'Adresse': 'Address Line One \n Address Line Two',
    'Téléphone': '0X XX XX XX XX',
    'Site': 'https://example.com/'
  },
  'Some Other Section': {
    'field 1': 'some info field 2 : __', 'field 3': 'some other info'
  }
}

Note: field 2 is merged into field 1 value because there's nothing separating them in the HTML, so there's no way to know if the key should be 2 or field 2 or info field 2 or... so the function assumes that there is a maximum of one field per NavigableString; and 'Some Section' only has a string value instead of a dictionary since there doesn't seem to be any :s separating field names from the relevant info.




Получение только одного фрагмента текста

Если вам действительно нужен только текст между двумя словами, вы можете просто использовать

def get_textchunk(word1, word2, text):
    if not (word1 in text and word2 in text): return ''
    return text.split(word1)[-1].split(word2)[0]
    ## can refine with more conditions/string-manipulations/regex/etc

get_textchunk('Adresse :', 'Téléphone :', soup.get_text(' '))

Однако, если вы не уверены в имени следующего поля, но уверены, что имена полей разделены :, вы можете использовать эту версию get_section_info:

def get_text_by_field(soupX, fieldName):
    fsCond = lambda s: s and ':' in s and s.split(':')[0].strip()==fieldName
    fieldStr = soupX.find(string=fsCond)
    hList, myText = [f'h{i}' for i in range(1,7)], fieldStr.split(':',1)[1]
    for ns in (fieldStr.next_siblings if fieldStr else []):
        if ns.name in hList: break ## stop when you reach the next section
        if not ((isinstance(ns,str) and not ns.PREFIX) or ns.name): continue 

        nsStr = ' '.join((ns if isinstance(ns,str) else ns.get_text(' ')).split())
        if ':' in nsStr and not nsStr.startswith('http'): break

        if ns.name == 'br': myText += ' \n'
        elif nsStr: myText += (' ' + nsStr)
    return myText.strip()

то get_text_by_field(soup, 'Adresse') должен вернуться

'Address Line One \n Address Line Two'

Может быть, вы можете попробовать преобразовать строки текста в одну строку. Я думаю, что тип вашего текста на самом деле представляет собой список, а не строку.

print(type(text)) to find the type of your text

Если это список, то:

list = ["Adresse : fffgdfdgfrrrere",
"rrgegreggregr",
"Téléphone : egrrgerererg"]

text = ' '.join(list)
print(text)

Затем:

text = "Adresse: fffgdfdgfrrrere rrgegreggregr Téléphone: egrrgerererg"
def get_textchunk(word1, word2, text):
            new_text = text.split(word1)
            new_text = new_text[1]
            newnew_text = new_text.split(word2)
            return newnew_text
print(get_textchunk('Adresse: ',' Téléphone', text)[0])

Ответ: "fffgdfdgfrrrere rrgegreggregr"

Другие вопросы по теме