D4Vinci/Scrapling · error · ExpressionError
The pseudo-element ::{pseudo_element} is unknown
Error message
The pseudo-element ::{pseudo_element} is unknown What it means
Raised by the non-functional branch of `xpath_pseudo_element` in scrapling/core/translator.py:105. Simple pseudo-elements (no parentheses) are dispatched to `xpath_<name>_simple_pseudo_element`; Scrapling only registers `::text` (plus cssselect's built-ins where applicable). Using any other simple pseudo-element such as `::before`, `::after`, `::first-line`, `::placeholder`, or `::marker` raises `ExpressionError` because pseudo-elements that exist only in browser rendering have no XPath representation.
Source
Thrown at scrapling/core/translator.py:105
# https://github.com/python/mypy/issues/14757
xpath = super().xpath_element(selector) # type: ignore[safe-super]
return XPathExpr.from_xpath(xpath)
def xpath_pseudo_element(self, xpath: OriginalXPathExpr, pseudo_element: PseudoElement) -> OriginalXPathExpr:
"""
Dispatch method that transforms XPath to support the pseudo-element.
"""
if isinstance(pseudo_element, FunctionalPseudoElement):
method_name = f"xpath_{pseudo_element.name.replace('-', '_')}_functional_pseudo_element"
method = getattr(self, method_name, None)
if not method: # pragma: no cover
raise ExpressionError(f"The functional pseudo-element ::{pseudo_element.name}() is unknown")
xpath = method(xpath, pseudo_element)
else:
method_name = f"xpath_{pseudo_element.replace('-', '_')}_simple_pseudo_element"
method = getattr(self, method_name, None)
if not method: # pragma: no cover
raise ExpressionError(f"The pseudo-element ::{pseudo_element} is unknown")
xpath = method(xpath)
return xpath
@staticmethod
def xpath_attr_functional_pseudo_element(xpath: OriginalXPathExpr, function: FunctionalPseudoElement) -> XPathExpr:
"""Support selecting attribute values using ::attr() pseudo-element"""
if function.argument_types() not in (["STRING"], ["IDENT"]): # pragma: no cover
raise ExpressionError(f"Expected a single string or ident for ::attr(), got {function.arguments!r}")
return XPathExpr.from_xpath(xpath, attribute=function.arguments[0].value)
@staticmethod
def xpath_text_simple_pseudo_element(xpath: OriginalXPathExpr) -> XPathExpr:
"""Support selecting text nodes using ::text pseudo-element"""
return XPathExpr.from_xpath(xpath, textnode=True)
class HTMLTranslator(TranslatorMixin, OriginalHTMLTranslator):
def css_to_xpath(self, css: str, prefix: str = "descendant-or-self::") -> str:View on GitHub (pinned to 5d213a2d47)
Solutions
- Remove rendering-only pseudo-elements (`::before`, `::after`, `::placeholder`, `::first-line`, ...) from the selector — their content is not in the HTML tree.
- To get `::before/::after` content, read the page's CSS (or rendered styles via the browser engine) instead of the DOM.
- Use `::text` for text nodes and `::attr(name)` for attributes — these are the two Scrapling adds.
- Test selectors in isolation (`Selector('<html>...</html>').css(sel)`) to find the offending one quickly.
Example fix
# before
page.css('button::before') # ExpressionError: unknown pseudo-element
# after
btn = page.css_first('button')
css_content = btn.pseudo_before_content # or inspect stylesheet / use browser evaluation Defensive patterns
Strategy: validation
Validate before calling
import re
SUPPORTED_SIMPLE = {'text'}
def check_simple_pseudos(css: str) -> list[str]:
return [name for name in re.findall(r'::([a-zA-Z-]+)(?!\()', css) if name not in SUPPORTED_SIMPLE] Try / catch
try:
txt = page.css('p::first-line')
except Exception as e:
if 'unknown' in str(e) and '::' in str(e):
txt = page.css('p::text') # fall back to the full text node
else:
raise Prevention
- Remember ::before/::after/::placeholder are rendering constructs, absent from the DOM.
- Validate selectors against the supported set before passing them to .css().
- Prefer element.attrib and text extraction over pseudo-elements in generated code.
When it happens
Trigger: `selector.css('p::first-line')`, `selector.css('input::placeholder')`, `selector.css('q::before')` — any `::<name>` without parentheses other than `::text` (and `::attr()` which is functional).
Common situations: Selectors copied from CSS stylesheets or DevTools that target visual pseudo-elements; expecting `::before`/`::after` content to be extractable (it lives in CSS, not the DOM); migrating from BeautifulSoup/lxml code that silently ignored unknown pseudo-elements.
Related errors
- The functional pseudo-element ::{pseudo_element.name}() is u
- Expressions of type {__name__}.XPathExpr can ony join expres
- Expected a single string or ident for ::attr(), got {functio
- Storage system must implement `save` method
- Storage system must implement `retrieve` method
AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14).
Data as JSON: /api/errors/bca03ce4deb7a3f0.
Report an issue: GitHub.