cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 216 of 218
Ideas this builds on
High-level design216 / 218

Design a polite web crawler

Picture

Discovered URLs wait for permission and scheduling. A seen set prevents repeatedly adding the same canonical URL.

Predict

Does one global requests-per-second limit guarantee polite spacing for each host?

Walk through the small example

No. One host can still receive a concentrated burst.

Mental model and runnable Python model

The frontier owns canonical URL identity, priority, retries, and per-host pacing. Discovery parses permitted links from fetched content and enqueues only in-scope candidates. Robots rules are a standard policy input, not authorization to bypass authentication or ignore terms. A real fetcher needs DNS and redirect revalidation, private-address restrictions, content/size limits, timeouts, and abuse protections. Canonicalization should not erase query distinctions blindly. Distributed workers need shared host ownership or coordination so local pacing does not multiply across machines.

Requirements and frontier

Define permitted domains, crawl purpose, freshness, depth, byte budget, and retention. The frontier stores canonical URL, host, priority, attempt count, next eligible time, and status. Use stable deduplication with an explicit revisit policy.

Fetch and discovery

Before fetching, apply policy and per-host scheduling. The fetcher enforces timeouts, redirect limits, public-network restrictions, response-size limits, and supported content types. Parse bounded content and enqueue only permitted in-scope links.

Distributed ownership

Assign hosts to schedulers or coordinate host budgets so many workers do not independently burst against the same site. Keep frontier state durable enough to recover, and separate transient fetch failures from permanent policy rejection.

Limits and safety

Honor robots rules and site access policies; do not bypass authentication. URL normalization, DNS rebinding, redirects, compression bombs, and infinite query spaces require explicit safeguards. This course model schedules URLs but never fetches them.

What the function promises: Frontier schedules only explicitly allowlisted HTTPS hosts and a supplied robots-policy result. It performs no network fetch. It is not a complete SSRF filter or robots.txt parser.

from urllib.parse import urlsplit, urlunsplit

class Frontier:
    def __init__(self, hosts, spacing):
        if spacing < 0:
            raise ValueError("Invalid spacing")
        self.hosts, self.spacing = set(hosts), spacing
        self.seen, self.next_time = set(), {}
    def admit(self, url, now, robots_allows):
        parsed = urlsplit(url)
        host = parsed.hostname
        if (parsed.scheme != "https" or host not in self.hosts
                or parsed.username or parsed.password
                or parsed.port not in (None, 443) or not robots_allows(url)):
            return None
        canonical = urlunsplit(("https", host, parsed.path or "/", parsed.query, ""))
        if canonical in self.seen:
            return None
        at = max(now, self.next_time.get(host, now))
        self.next_time[host] = at + self.spacing
        self.seen.add(canonical)
        return at, canonical

frontier = Frontier({"example.com"}, 2)
assert frontier.admit("https://example.com/a", 0, lambda u: True)[0] == 0
assert frontier.admit("https://example.com/b", 0, lambda u: True)[0] == 2
assert frontier.admit("https://example.com/a#part", 0, lambda u: True) is None
assert frontier.admit("https://localhost/", 0, lambda u: True) is None

Work and storage: Expected O(1) local dedup and host scheduling, excluding URL parsing and real fetch work. Storage grows with discovered URLs and hosts.

When to recognize it: Honor applicable robots rules and access policies. Also prevent fetches into private networks, unsafe redirects, or unexpectedly large responses.

Check before applying it: Robots policy, host pacing, scope, and network-fetch safety are separate responsibilities.

Change one rule

An allowlisted hostname resolves to a private address or redirects there. Does this scheduler make fetching it safe?

See what changes

No. The fetch layer must validate resolved destinations and every redirect against network policy, with egress controls and bounded resolution behavior. No fetching occurs in this model.

Connect

Let work wait without losing its identity: A durable frontier separates URL discovery from controlled fetching.

sets: A seen set is useful only after choosing what counts as the same URL.