Skillversitas

Contents, Children and Descendants

A tag's children are the nodes directly inside it. Beautiful Soup exposes three related views: .contents (a list of direct children), .children (a generator over the same), and .descendants (a generator over everything nested, at any depth).

.contents - Direct Children as a List

from bs4 import BeautifulSoup

html = "<div><p>a</p><p>b</p><!-- note --></div>"
soup = BeautifulSoup(html, "html.parser")

print(soup.div.contents)
# [<p>a</p>, <p>b</p>, <!-- note -->]

print(len(soup.div.contents))  # 3

.contents is a plain list, so you can index and slice it: soup.div.contents[0] is the first child.

.children - Iterate Direct Children

for child in soup.div.children:
    print(child.name if child.name else repr(str(child)))

.children is a generator: it yields each direct child once, without building a list in memory. It also yields text nodes and comments, not just tags.

.descendants - Everything Nested

html = "<div><p><b>x</b></p></div>"
soup = BeautifulSoup(html, "html.parser")

for d in soup.div.descendants:
    print(repr(str(d))[:40])

.descendants walks the whole subtree in document order: tags, strings, and comments at every depth. It includes the whitespace text nodes between elements.

Which One to Use

  • .contents when you need a count, indexing, or one-off processing of direct children.
  • .children when you want to iterate direct children without materializing a list.
  • .descendants when you need every node in the subtree, for example to strip all text.

Summary

.contents gives a list of a tag's direct children, .children gives a generator over the same nodes, and .descendants gives a generator over the entire nested subtree. All three include text nodes and comments, so filter by type when you only want tags.