CSS selector syntax
Selectors are built from a few primitives. A bare tag name (a, div, h2) matches elements of that type. A dot prefixes a class (.product), a hash prefixes an id (#header), and square brackets match attributes ([data-id] for presence, a[href^="https"] for a value that starts with "https"). You combine these to narrow the match: div.card h3 means an h3 anywhere inside a div with class "card", while div.card > h3 means an h3 that is a direct child. Sibling combinators (+ for the next element, ~ for any later sibling) and pseudo-classes (:first-child, :nth-child(2)) handle position. Chaining without a space (a.btn.primary) requires all conditions on one element.
How scrapers use CSS selectors
Extraction is two steps: fetch the HTML, then query it with selectors. In Python, BeautifulSoup's select() and select_one() take a CSS selector and return matching elements; Scrapy and parsel offer .css(); in Node, Cheerio mirrors jQuery's $('.price'); and browser automation tools like Playwright and Puppeteer use selectors to both find and interact with elements (page.click('button.submit')). The skill is writing selectors that are specific enough to grab the right data but loose enough to survive small markup changes - anchoring on a stable class or data attribute rather than a brittle chain of div > div > div that breaks the moment the layout shifts.
CSS selectors vs XPath
CSS selectors and XPath are the two query languages for HTML, and most tools support both. CSS selectors are shorter and more readable for the common cases - selecting by class, id, or attribute - which is why they are the default for most scraping. XPath is more powerful: it can walk back up to a parent, select an element by its text content, or apply functions, none of which plain CSS can do. A practical rule: reach for CSS first because it is cleaner, and drop to XPath when you need to match on text or navigate upward through the tree. Getting selectors right matters more than which language you pick - and a parsing layer that returns structured fields, like an autoparse step, removes the need to hand-write selectors for common page types.
