knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
zuhtml implements a deliberately small subset of CSS Selectors and rejects everything else with an error. A selector either works exactly as it would in a browser or fails loudly: it never matches something partly.
library(zuhtml) doc <- html_parse(' <div id=main class="card wide"> <h2 class=title>One</h2> <p class="a b" lang=en-US>first</p> <p title="">second</p> <ul><li>1<li>2<li>3<li>4</ul> </div>')
| Kind | Examples |
|---|---|
| Type and universal | p, * |
| ID and class | #main, .card.wide |
| Attributes | [title], [lang=en-US], [class~=a], [lang\|=en], [href^=http], [href$=".pdf"], [href*=shop], with an i or s flag |
| Combinators | div p, div > p, h2 + p, h2 ~ p, and lists: h2, p |
| Pseudo-classes | :scope, :root, :empty, :first-child, :last-child, :only-child, :nth-child(an+b), :nth-of-type(an+b), :not() of one compound selector |
html_text(html_elements(doc, "h2 ~ p")) html_text(html_elements(doc, "li:nth-child(odd)")) html_text(html_elements(doc, "p:not([title])")) html_text(html_elements(doc, "[lang|=en]"))
:has(), other pseudo-classes, pseudo-elements (including Scrapy's
::text and ::attr()), namespace prefixes and the of S form of
:nth-child() are errors. The error says where:
try(html_elements(doc, "div:has(> h2)")) try(html_elements(doc, "p::text"))
Handle them by class, zuhtml_selector_error; the condition carries the
selector, the position and whether the form is unsupported or malformed.
As in a browser on an HTML page: element and attribute names match HTML
elements whatever their case, and SVG or MathML elements exactly. IDs and
classes are case-sensitive. Attribute values are case-sensitive, except
for the attributes HTML lists as case-insensitive (type, lang and
others); an i or s flag overrides either.
length(html_elements(doc, "P")) length(html_elements(doc, ".CARD")) length(html_elements(doc, "[lang=EN-US]")) length(html_elements(doc, "[lang=EN-US s]"))
Searching a document includes its <html> element. Searching below an
element excludes the element itself, unless :scope names it:
main <- html_element(doc, "#main") length(html_elements(main, ".card")) length(html_elements(main, ":scope.card")) html_name(html_elements(main, ":scope > *"))
The rest of a selector may match outside the context, as
querySelectorAll() does: "body h2" below #main finds the <h2>
even though <body> is outside it.
html_elements() on several nodes returns the union of their matches,
without duplicates, in document order. html_element() returns one
result per input node, a missing node where there is no match: use it to
pull one field out of each of many records.
<template> contents are never searched; reach them with
html_template_content().
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.