Quick Overview

This question evaluates skills in web crawling, URL parsing and fragment sanitization, graph traversal for deduplication, and concurrent programming for thread-safe crawling, and it falls under the Coding & Algorithms domain.

Design a single- and multi-threaded web crawler

Company: Anthropic

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

## Web Crawler (single-threaded, then multi-threaded) You are given: - A starting URL `startUrl` (e.g., `"http://news.example.com/a/index.html"`). - An interface `HtmlParser` with a method `getUrls(url)` that returns **all URLs** found on the page at `url`. Your task is to crawl web pages starting from `startUrl` and return all **unique** pages that are reachable by following links, subject to the rules below. ### Rules 1. **Same-hostname only:** Only crawl pages whose hostname is the same as the hostname of `startUrl`. - The hostname is the part between the scheme (`http://` or `https://`) and the next `/`. 2. **Fragment handling:** URLs may contain a fragment part starting with `#` (e.g., `http://a.com/x#section2`). - You must **strip the fragment** (remove `#` and everything after it) before: - deciding whether you have already visited the URL (deduplication), and - including the URL in the returned result. - Example: `http://a.com/x#p1` and `http://a.com/x#p2` should be treated as the **same page**: `http://a.com/x`. 3. **No other normalization:** Do **not** perform other URL normalization (e.g., do not canonicalize trailing slashes, default ports, query parameter ordering, etc.). Only strip the fragment. ### Part A — Single-threaded Implement a single-threaded crawler that returns the set/list of visited URLs (after stripping fragments), restricted to the same hostname. ### Part B — Follow-up: Multi-threaded Now implement a multi-threaded crawler to speed up crawling. - Multiple worker threads may call `HtmlParser.getUrls` concurrently. - Your solution must be thread-safe and must not crawl the same sanitized URL more than once. ### Output Return all unique sanitized URLs that are reachable from `startUrl` and satisfy the hostname constraint. ### Assumptions / Notes - `HtmlParser.getUrls(url)` is a black box and may be slow (network/IO-like). - The link graph may contain cycles. - URLs returned by `getUrls` are absolute URLs.

Quick Answer: This question evaluates skills in web crawling, URL parsing and fragment sanitization, graph traversal for deduplication, and concurrent programming for thread-safe crawling, and it falls under the Coding & Algorithms domain.

Part 1: Single-Threaded Web Crawler

You are given a starting URL `start_url` and a dictionary `web` that simulates `HtmlParser.getUrls(url)`. For any crawled page `u`, its outgoing links are `web.get(u, [])`. Crawl all pages reachable from `start_url` using a single thread, with these rules: 1. Only crawl URLs whose hostname matches the hostname of `start_url`. 2. Before checking whether a URL was already visited, strip its fragment part (`#...`). 3. Return each page only once, using its fragment-free form. 4. Do not perform any other normalization. For example, `http://a.com`, `http://a.com/`, and `http://a.com:80` are all different URLs. To make the output deterministic, return the visited URLs as a lexicographically sorted list. Notes: - `web` keys represent fragment-free page URLs. - If a crawled page is missing from `web`, treat it as a page with no outgoing links.

Constraints

  • 0 <= len(web) <= 10^4
  • 0 <= total number of links across all pages <= 5 * 10^4
  • All URLs are absolute and start with `http://` or `https://`
  • Only fragment stripping is allowed; no other URL normalization may be applied
  • The link graph may contain cycles

Examples

Input: ('http://news.example.com/a/index.html#top', {'http://news.example.com/a/index.html': ['http://news.example.com/b#section', 'http://other.example.com/x', 'http://news.example.com/c', 'http://news.example.com/b#other'], 'http://news.example.com/b': ['http://news.example.com/c#frag', 'http://news.example.com/a/index.html#again'], 'http://news.example.com/c': ['http://news.example.com/c#self']})

Expected Output: ['http://news.example.com/a/index.html', 'http://news.example.com/b', 'http://news.example.com/c']

Explanation: The crawler starts at the fragment-free URL `http://news.example.com/a/index.html`, ignores the external hostname, removes fragments before deduplication, and reaches pages a, b, and c.

Input: ('https://a.com/home', {'https://a.com/home': ['https://a.com/about#team', 'https://b.com/out', 'https://a.com/about#company'], 'https://a.com/about': ['https://a.com/home#top', 'https://a.com/about#self']})

Expected Output: ['https://a.com/about', 'https://a.com/home']

Explanation: Only URLs on hostname `a.com` are crawled. The two fragment variants of the about page collapse into one visited URL.

Hints

  1. Strip the fragment from every URL as soon as you read it, before deduplication.
  2. A DFS or BFS with a `visited` set is enough once you can extract the hostname.

Part 2: Multi-Threaded Web Crawler

You are given the same simulated web as in Part 1: a starting URL `start_url` and a dictionary `web` where `web.get(u, [])` represents the URLs returned by `HtmlParser.getUrls(u)`. Implement a multi-threaded crawler that follows the same rules: 1. Only crawl URLs whose hostname matches the hostname of `start_url`. 2. Strip fragments (`#...`) before deduplication and before adding a URL to the result. 3. Do not perform any other normalization. 4. The same sanitized URL must never be crawled more than once, even when multiple threads run concurrently. Return the final set of visited pages as a lexicographically sorted list. Notes: - `web` keys represent fragment-free page URLs. - If a crawled page is missing from `web`, treat it as having no outgoing links. - Your design should be safe under concurrent crawling: no page crawled twice, no lost pages. - Language note: Java and C++ can spawn real threads in this console. The Python sandbox runs single-threaded, so submit a correct sequential traversal in Python and describe the locking and queue design in your answer. The grader compares the final sorted list, which is identical either way.

Constraints

  • 0 <= len(web) <= 10^4
  • 0 <= total number of links across all pages <= 5 * 10^4
  • All URLs are absolute and start with `http://` or `https://`
  • Only fragment stripping is allowed; no other URL normalization may be applied
  • The link graph may contain cycles
  • The design must be safe under concurrent crawling (see the language note above)

Hints

  1. Mark a URL as visited *before* handing it to a worker, not after you crawl it. That single ordering is what stops two workers racing onto the same page.
  2. A thread-safe work queue is the natural way to hand pages to workers — be ready to say how you would size the pool and decide the crawl is finished, which is what the interviewer is probing.
  3. Language note: Java and C++ can spawn real threads here. The Python sandbox runs single-threaded (thread creation is disabled), so write a correct sequential traversal in Python and describe the locking design in words — the grader compares the final sorted list, which is the same either way.

Loading coding console...