find vs find_all
find() and find_all() share the same filter syntax but differ in return type: find() gives you the first match (or None), find_all() gives you a list of all matches (possibly empty). Choosing well between them keeps your scraping code short and safe.
Return Types at a Glance
| find() | find_all() | |
|---|---|---|
| Match | first matching Tag | list of matching Tags |
| No match | None | empty list [] |
| Limit | n/a (always one) | limit=N caps the scan |
| Internal relation | find is find_all(limit=1) taking [0] | |
Same Filters, Two Calls
from bs4 import BeautifulSoup
html = "<div><p class="note">one</p><p class="note">two</p></div>"
soup = BeautifulSoup(html, "html.parser")
first = soup.find("p", class_="note") # a Tag
all_ = soup.find_all("p", class_="note") # a list
print(first.get_text()) # one
print(len(all_)) # 2
Guarding Against None
The classic scraping crash is calling .text on a None result. Use a truthiness check or a short-circuit:
tag = soup.find("p", class_="note")
text = tag.get_text() if tag else "missing"
print(text)
Choosing Between Them
- You need exactly one value (a title, a price): find() plus a None guard.
- You need a collection (all products, all links): find_all() and loop.
- You are not sure whether the page has one or many: find_all() and handle len() == 0.
Summary
find() returns the first match or None; find_all() returns a list of all matches, possibly empty, and accepts limit. Both accept identical filters. Prefer find for single values with a None guard, find_all for collections, and never call methods on a find() result without checking it is not None.