fastrag.ingestion.steps.fetching.sitemap#
Sitemap-driven fetching: expand sitemap.xml, then fetch what it lists.
Ported from src/fastrag/steps/fetching/sitemap.py onto the new
Fetcher/SourceStep base. Caching is per page (one bucket per crawled
URL, via the targets/evaluate_target hooks
fastrag.ingestion.steps.base fans out over) rather than per crawl, so a
sitemap that gains one URL still serves every previously-fetched page from
the cache — see docs/specification/API.md’s “cache each page independently
to increase cache hit rate.”
Module Attributes
How many nested |
Classes
|
Expand |
- fastrag.ingestion.steps.fetching.sitemap.MAX_INDEX_DEPTH = 3#
How many nested
<sitemapindex>levels to follow before giving up. Real sites use one; a deeper chain is far more likely to be a loop.
- class fastrag.ingestion.steps.fetching.sitemap.SitemapCrawler(*, url, include=None, exclude=None, max_urls=None, renderer=None, extract_pdfs=True, headers=None, timeout=30.0, follow_redirects=True, user_agent='fastrag/0.1 (+https://github.com/AgrospAI/fastrag)', cache=None, policy=None, cache_validation_interval=None)[source]#
Bases:
FetcherExpand
sitemap.xml, then fetch what it lists.The right default for a website: the site itself publishes the canonical page list, so a rerun picks up new pages without editing any code. Nested
<sitemapindex>documents are followed.from fastrag.ingestion.steps.fetching import SitemapCrawler crawler = SitemapCrawler( url="https://example.com/sitemap.xml", include=["https://example.com/docs/*"], cache=cache, )
- Parameters:
- config()[source]#
This crawler’s cache fingerprint: only what changes a page’s bytes.
url,include,exclude, andmax_urlsdecide which pages are discovered, not what a given page returns, so they are deliberately excluded here — otherwise raisingmax_urlswould invalidate every already-cached page’s bucket for no reason. Per-page cache ids already encode the page’s own URL as theirtarget.
- async targets(context)[source]#
Return the filtered page URLs the sitemap lists, normalized and deduplicated.
Costs one request per sitemap document, and no page downloads. Called by the base class’s per-target cache wrap before deciding which pages need
evaluate_target().Sitemaps routinely list one page under several spellings (
/auditand/audit/, a stray#fragment, an explicit:443). Those all collapse to onenormalize_uri(), and so to oneSource.id, so they are collapsed here too — into a single target and a single cache bucket, rather than fetched repeatedly and written over each other.include/excludestill see the sitemap’s own spelling for glob patterns; exact URLs match normalized spellings too.- Parameters:
context (ExecutionContext)
- Return type:
- async evaluate_target(target, context)[source]#
Fetch one page URL, yielding its
Sourcethen one per routed embed.- Parameters:
target (str)
context (ExecutionContext)
- Return type:
- async evaluate(context)[source]#
Fetch every listed page, uncached, bounded by
policy.concurrency.Used directly when no cache is in effect — the per-target cache wrap (
targets()/evaluate_target()) is what applies when one is.- Parameters:
context (ExecutionContext)
- Return type:
- async is_source_modified(source_id, cached_etag, cached_last_modified, cached_content_hash)[source]#
Conditional freshness check: ETag, then Last-Modified, then content hash.
source_idis the cached entry’s normalized id, which — unlikeAPI.md’s illustrative example — still carries a scheme, so it is directly usable as a fetchable URI here. A server that answers none of the three (refusesHEADand gives no reusable validator) reads as modified only implicitly: the refetch-and-compare fallback below always produces a definite answer.
- async aclose()[source]#
Release the shared HTTP client and renderer resources. Idempotent.
- Return type:
None
- property cache: CacheStore | Literal[False] | None#
Return the cache explicitly configured for this step.
- canonical_uri(uri)#
Identity under which
uriis fetched, to deduplicate equivalent spellings.
- property config_hash: str#
A stable hash of this step’s class name and
config().Two identically configured steps of the same class hash equal; changing any declared config value changes the hash; the hash is stable across processes. Used as part of every cache id this step’s evaluation reads or writes.
- effective_policy(context)#
Resolve this step’s policy over the one inherited from
context.The step’s own explicitly-set fields take priority; everything else falls through to the pipeline (or enclosing router/aggregator) policy.
- Parameters:
context (ExecutionContext)
- Return type:
- event_name: str = 'Fetching'#
The stage this step’s work belongs to, e.g.
"Chunking".Declared as a plain class attribute by a family base class, and inherited by every concrete step in that family:
class Chunker(DocumentStep, ABC): event_name = "Chunking" class ChunkerRouter(RoutedStep[Document], Chunker): ... # -> "Chunking", inherited from `Chunker`
A concrete step overrides it to opt out of its family’s label:
class ChunkerRouter(RoutedStep[Document], Chunker): event_name = "ChunkerRouter" # -> "ChunkerRouter"
Resolution walks the MRO for the first class that declares it in its own class body (so a mixin listed first, e.g.
RoutedStep, contributes nothing unless it declares one itself), and falls back to the class’s own name when nothing in the MRO does — a step family that never declares anevent_namestill labels each of its steps distinctly rather than collapsing them under one blank heading. That fallback is computed per instance rather than assigned onto the class: assigning it would make it look “declared” to every subclass, which would then inherit their base’s name instead of getting their own.
- async fetch(uri)#
Fetch one URL in-process, uncached. Needed to be a
route()target.- Raises:
fastrag.exceptions.ConfigurationError – This fetcher cannot fetch an arbitrary URL.
- Parameters:
uri (str)
- Return type:
- route(filter_rule, fetcher)#
Delegate the URLs matching
filter_ruletofetcher.The filter sees a content-less
Sourcecarrying only the URL, so URL-based filters such asURLFilterapply. Routes are tried in registration order, and the first match wins.
- route_for(uri)#
The fetcher routed to
uri, orNoneto fetch it normally.
- routes_config()#
Routed fetchers’ fingerprints, for inclusion in a crawler’s
config().
- async run()#
Execute this step independently and collect every item.
Builds a default
ExecutionContextwhen none is installed (this step’s ownpolicy, or a freshPolicy). Intended primarily for testing and standalone use — pipeline-wide event observation isPipeline’s job.- Return type:
list[T]
- property upstream: PipelineStep[Any] | None#
Return the upstream step bound via
__call__, orNone.Read-only counterpart to
__call__’sself._upstreamassignment — lets external code (e.g.Pipeline, walking a graph from its root to classify each step by position) introspect composition without reaching into a private attribute.