bs4 discard all HTML before a specific tag

Viewed 55

Versions used: BS4, lxml, Python3.9

Say I have some HTML:

<div>
    <p>Hello</p>
    <h1>hi</h1>
    <div id="hello"></div>
    <h1>Hello</h1>
</div>

If I have some HTML selected: legal_div = soup.find(id="hello"), how could I discard or disregard any tag before that legal_div. I'd prefer to use lxml, but if it isn't possible, then html.parser is fine as well.

Edit: When I say discard, I mean that if I were to search for any <h1> tags, I should only see "Hello", not "hi"

2 Answers

I'm not quite sure what you want. If you strictly just need to find that specific <h1> tag, then do as Andrej has it and get that element, and find_next() h1 tag.

But if you need to alter the html, you can get all the h1 tags and use .decompose() any that didnt follow your specified criteria:

from bs4 import BeautifulSoup

html = '''<div>
    <p>Hello</p>
    <h1>hi</h1>
    <div id="hello"></div>
    <h1>Hello</h1>
</div>'''

soup = BeautifulSoup(html, 'html.parser')
print('\tBefore:\n\n%s' %soup)

all_h1 = soup.find_all('h1')
print('\n',all_h1)


for each in all_h1:
    if each.find_previous().name == 'div' and each.find_previous().attrs['id'] == 'hello':
        continue
    else:
        each.decompose()


print('\n\n\tAfter:\n\n%s' %soup)
all_h1 = soup.find_all('h1')
print('\n',all_h1)

Output:

Before:

<div>
<p>Hello</p>
<h1>hi</h1>
<div id="hello"></div>
<h1>Hello</h1>
</div>

 [<h1>hi</h1>, <h1>Hello</h1>]

After:

<div>
<p>Hello</p>

<div id="hello"></div>
<h1>Hello</h1>
</div>

 [<h1>Hello</h1>]

You can use legal_div.find_next('h1'). For example:

from bs4 import BeautifulSoup

html_doc = """
<div>
    <p>Hello</p>
    <h1>hi</h1>
    <div id="hello"></div>
    <h1>Hello</h1>
</div>
"""

soup = BeautifulSoup(html_doc, "html.parser")

legal_div = soup.find(id="hello")
next_h1 = legal_div.find_next("h1")

print(next_h1)

Prints:

<h1>Hello</h1>

Or using ~ in CSS selector:

all_next_h1 = soup.select("#hello ~ h1")
print(all_next_h1)

Prints:

[<h1>Hello</h1>]
Related