Prerequisites
- You’ve read the Getting started page and know how to create and run a basic spider.
Concurrency Control
The spider system uses three class attributes to control how aggressively it crawls:concurrent_requests_per_domain is set, each domain gets its own concurrency limiter in addition to the global limit. This is useful when crawling multiple domains simultaneously — you can allow high global concurrency while being polite to each individual domain.
Rate Limiting Implementation
The rate limiting logic is implemented in theCrawlerEngine:
engine.py:71-77
engine.py:88-92
Using uvloop
Thestart() method accepts a use_uvloop parameter to use the faster uvloop/winloop event loop implementation, if available:
uvloop (Linux/macOS) or winloop (Windows) separately.
Pause & Resume
The spider supports graceful pause-and-resume via checkpointing. To enable it, pass acrawldir directory to the spider constructor:
How It Works
-
Pausing: Press
Ctrl+Cduring a crawl. The spider waits for all in-flight requests to finish, saves a checkpoint (pending requests + a set of seen request fingerprints), and then exits. -
Force stopping: Press
Ctrl+Ca second time to stop immediately without waiting for active tasks. -
Resuming: Run the spider again with the same
crawldir. It detects the checkpoint, restores the queue and seen set, and continues from where it left off — skippingstart_requests(). - Cleanup: When a crawl completes normally (not paused), the checkpoint files are deleted automatically.
Checkpoint Implementation
The pause handling logic is implemented in the engine:engine.py:165-182
engine.py:184-189
Knowing If You’re Resuming
Theon_start() hook receives a resuming flag:
Streaming
For long-running spiders or applications that need real-time access to scraped items, use thestream() method instead of start():
start():
stream()must be called from an async context- Items are yielded one by one as they’re scraped, not collected into a list
- You can access
spider.statsduring iteration for real-time statistics
Streaming Implementation
The streaming logic uses memory channels:engine.py:313-334
spider.pause() to shut down the spider programmatically. If you use it without enabling the checkpoint system, it will just close the crawl.
Lifecycle Hooks
The spider provides several hooks you can override to add custom behavior at different stages of the crawl:on_start
Called before crawling begins. Use it for setup tasks like loading data or initializing resources:spider.py:164-172
on_close
Called after crawling finishes (whether completed or paused). Use it for cleanup:spider.py:174-176
on_error
Called when a request fails with an exception. Use it for error tracking or custom recovery logic:spider.py:178-184
on_scraped_item
Called for every scraped item before it’s added to the results. Return the item (modified or not) to keep it, or returnNone to drop it:
spider.py:186-188
start_requests
Overridestart_requests() for custom initial request generation instead of using start_urls:
spider.py:141-156
Results & Statistics
TheCrawlResult returned by start() contains both the scraped items and detailed statistics:
CrawlStats Details
TheCrawlStats dataclass tracks comprehensive information:
result.py:41-62
Detailed Stats
Logging
The spider has a built-in logger accessible viaself.logger. It’s pre-configured with the spider’s name and supports several customization options:
Logger Initialization
The logger is initialized in the Spider’s__init__ method:
spider.py:101-122