CSS Selectors with select()
Instead of the Python filter syntax, you can select elements with CSS selectors through .select() (returns a list) and .select_one() (returns the first match or None). If you already think in CSS selectors, this is the most direct way to express a query.
Basic Selectors
from bs4 import BeautifulSoup
html = '''
<div id="main">
<p class="intro">Hi</p>
<ul><li class="first">a</li><li>b</li></ul>
<a href="x" data-rank="1">link</a>
</div>
'''
soup = BeautifulSoup(html, "html.parser")
print(soup.select("p.intro")) # class selector
print(soup.select("#main")) # id selector
print(soup.select("div p")) # descendant selector
print(soup.select("[data-rank]")) # attribute existence
print(soup.select("a[href^='x']")) # attribute starts-with
select_one for Single Values
intro = soup.select_one("p.intro")
print(intro.get_text() if intro else "missing")
print(soup.select_one("li.first").get_text()) # a
Complex Queries
Standard CSS works: commas for alternation, child combinators, and common pseudo-classes:
print(soup.select("li.first, li:last-child"))
print(soup.select("ul > li"))
print(soup.select("a[href$='.pdf']"))
CSS Selectors vs find
- CSS selectors are shorter and familiar, and great for structural queries like "a price span inside a product card".
- find with attribute/regex filters is more flexible for non-CSS logic (e.g., filter on text content or a Python function).
- Both return Tag objects; the rest of the API (get_text, attributes) is identical.
Summary
select() and select_one() let you query the tree with CSS selectors: tags, classes, ids, descendants, attribute conditions, and combinators. Use them for concise structural queries, and fall back to find with regex or function filters when you need logic CSS cannot express.