codex/web/selectolax_scraping.cat
# Parsing HTML avec selectolax
# selectolax utilise le moteur Lexbor (C) -- 10-30x plus rapide que BeautifulSoup
# Complète httpx : fetch (httpx) → parse (selectolax) → extract (Catnip)
#
# Exécuter:
# catnip docs/codex/web/selectolax_scraping.cat
selectolax = import("selectolax.parser")
# HTML de test -- une page de résultats fictive
HTML = '
<html>
<head><title>Résultats de recherche</title></head>
<body>
<nav class="breadcrumb">
<a href="/">Accueil</a> / <a href="/search">Recherche</a>
</nav>
<h1>3 résultats pour "catnip"</h1>
<ul id="results">
<li class="result" data-score="0.98">
<a href="/doc/intro" class="title">Introduction à Catnip</a>
<span class="meta">Guide -- 5 min de lecture</span>
</li>
<li class="result" data-score="0.85">
<a href="/doc/broadcast" class="title">Broadcasting</a>
<span class="meta">Référence -- 12 min de lecture</span>
</li>
<li class="result featured" data-score="0.72">
<a href="/doc/patterns" class="title">Pattern Matching</a>
<span class="meta">Tutoriel -- 8 min de lecture</span>
</li>
</ul>
<table class="stats">
<tr><th>Métrique</th><th>Valeur</th></tr>
<tr><td>Temps</td><td>0.042s</td></tr>
<tr><td>Index</td><td>12,847 pages</td></tr>
</table>
<footer><p>Généré en 42ms</p></footer>
</body>
</html>
'
tree = selectolax.HTMLParser(HTML)
# Accès direct aux éléments structurels
print("⇒ Éléments structurels")
print(" <title>:", tree.css_first("title").text())
print(" <h1>:", tree.css_first("h1").text())
# Sélecteurs CSS -- même syntaxe que les navigateurs
print("\n⇒ Sélecteurs CSS")
# Par classe
results = tree.css("li.result")
print(" li.result:", len(results), "éléments")
# Par id
ul = tree.css_first("#results")
print(" #results tag:", ul.tag)
# Combiné
featured = tree.css_first("li.featured a.title")
print(" li.featured a.title:", featured.text())
# Extraction de données structurées
print("\n⇒ Extraction des résultats")
for node in tree.css("li.result") {
title = node.css_first("a.title")
meta = node.css_first("span.meta")
score = node.attributes["data-score"]
href = title.attributes["href"]
print(" [" + score + "]", title.text(), "→", href)
print(" ", meta.text())
}
# Attributs et navigation
print("\n⇒ Attributs")
links = tree.css("nav.breadcrumb a")
for a in links {
print(" <a href=\"" + a.attributes["href"] + "\">" + a.text() + "</a>")
}
# Parsing de table HTML
print("\n⇒ Table de stats")
rows = tree.css("table.stats tr")
for row in rows {
cells = row.css("td")
if len(cells) == 2 {
print(" ", cells[0].text(), ":", cells[1].text())
}
}
# Texte brut (strip tags)
print("\n⇒ Texte brut du footer")
footer = tree.css_first("footer")
print(" ", footer.text(strip=True))
# Combinaison avec httpx (pattern complet)
# fetch = httpx.get("https://example.com")
# tree = selectolax.HTMLParser(fetch.text)
# data = tree.css("article h2").[text()]
print("\n⇒ Terminé")