I am writing some HTML processing and am loving BS4. I do find it a bit lengthy and was hoping there was some better way to deal with this.
I would love to chain my finds together like this:
soup.find('li', class_='positions').find('span', class_='list-value').getText()
Instead when the first find doesn’t find anything, it returns None
and then the next find fails on that as expected.
I rewrote as two lines and it seems ok, but it would be preferred to have some sort of ?:
conditional operator in there like I do in c#.
elem_sup_position = soup.find('li', class_='positions')
sup_position = elem_sup_position.find('span', class_='list-value').getText() if elem_sup_position is not None else ''
I know I could probably rewrite it as this but I hate executing the first find twice to save 1 line of code! Is there a slicker way to do this? I have a lot of these.
sup_position = result.find('li', class_='positions').find('span', class_='list-value').getText() if result.find('li', class_='positions') else None
2
You could use css selectors
to chain your selection:
soup.select_one('li.positions span.list-value')
and you could use the walrus operator
(since Python 3.8) to avoid writing your selection twice:
result.getText() if (result := soup.select_one('li.positions span.list-value')) else None
Example
from bs4 import BeautifulSoup
soup = BeautifulSoup('<li class="positions"><span class="list-value">some text</span></li>')
### your way with find
result.find('span', class_='list-value').getText() if (result := soup.find('li', class_='positions')) else None
### css selectors
result.getText() if (result := soup.select_one('li.positions span.list-value')) else None
1