Derive a link's container component from its DOM path
Source:R/screaming_frog_contract.R
sf_container_from_path.RdReduces a Screaming Frog Link Path to the **component
the link sits in**, stable across every page that component appears on.
This is the identity the boilerplate detector conditions on: see
pagerank()'s container_col.
Two steps:
**Strip numeric predicates, keep class predicates.** Screaming Frog's
Link Pathis a hybrid, using[@class='...']where classes exist and positional[n]elsewhere. Positions are unstable — the same recycled call-to-action lands atp[5]on a post with four preceding paragraphs andp[3]on a shorter one — while a class is exactly the stable component identifier we want.**Drop the trailing
<a>step**, whatever predicate it carries. The anchor's own class describes the link, not the component containing it.
Note this cuts the **opposite** way from
sf_region_from_path(), which strips class predicates so that a
div[@class='site-footer'] is not mistaken for a <footer>. The
two answer different questions — *which region is this* versus *is this the
same component* — and the inconsistency is deliberate.
Value
A character vector the same length as x holding the container
path. Blank strings and NA yield NA, leaving those rows
unscored by the detector.
See also
[pagerank()], whose `container_col` consumes the result.
Other Screaming Frog toolkit:
sf_contract(),
sf_graph_eligible(),
sf_normalize_position(),
sf_parse_follow(),
sf_read_input(),
sf_region_from_path(),
sf_rel_nofollow()
Examples
sf_container_from_path(c(
"//body/main/article/p[5]/a[1]", # positions stripped
"//body/main/article/p[3]/a[1]", # ... so these two agree
"//body/div[@class='cta']/a", # class kept as the component identity
"//body/div[@class='cta']/a[@class='btn']" # anchor's own class dropped
))
#> [1] "//body/main/article/p" "//body/main/article/p"
#> [3] "//body/div[@class='cta']" "//body/div[@class='cta']"