CRAWLER ENGINE
Omnivore's crawler engine is a high-performance, parallel web crawler built with Rust and Tokio. It features intelligent URL frontier management, politeness controls, and automatic rate limiting.
10,000+ pages/min
Process thousands of pages per minute with parallel workers
Respectful
Built-in robots.txt compliance and rate limiting
Smart Frontier
Intelligent URL management with priority queuing
ARCHITECTURE OVERVIEW
Core Components
1. URL Frontier
The frontier manages the queue of URLs to be crawled. It implements priority queuing, deduplication, and depth tracking:
- Priority Queue: URLs are prioritized based on domain importance and depth
- Deduplication: Bloom filters prevent crawling the same URL multiple times
- Depth Control: Configurable maximum depth to prevent infinite crawling
- Domain Buckets: URLs grouped by domain for politeness enforcement
2. Worker Pool
Parallel workers powered by Tokio's async runtime handle concurrent page fetching:
RUST001// Worker configuration002pub struct WorkerConfig {003 pub num_workers: usize, // Number of parallel workers004 pub timeout: Duration, // Request timeout per page005 pub retry_limit: u32, // Max retries for failed requests006 pub user_agent: String, // Custom user agent string007}
3. Politeness Engine
Ensures respectful crawling behavior across domains:
- Robots.txt Parser: Automatic fetching and caching of robots.txt files
- Rate Limiting: Per-domain request delays (default: 1 second)
- Crawl-Delay: Respects crawl-delay directives from robots.txt
- Concurrent Limits: Maximum concurrent requests per domain
4. Content Processor
Extracts and processes content from fetched pages:
- HTML Parsing: Fast HTML parsing with scraper crate
- Link Extraction: Automatic discovery of internal and external links
- Content Extraction: Text, metadata, and structured data extraction
- JavaScript Support: Optional headless browser for JS-heavy sites
CONFIGURATION
Basic Configuration
TOML001[crawler]002# Number of parallel workers003workers = 10004005# Maximum crawl depth006max_depth = 3007008# Request timeout in seconds009timeout = 30010011# User agent string012user_agent = "Omnivore/0.1.0"013014# Respect robots.txt015respect_robots = true016017# Delay between requests to same domain (ms)018politeness_delay = 1000
Advanced Configuration
TOML001[crawler.advanced]002# URL frontier settings003frontier_size = 100000004priority_queue = true005bloom_filter_size = 10000000006007# Network settings008max_redirects = 5009connect_timeout = 10010dns_cache_size = 1000011012# Content settings013max_page_size = 10485760 # 10MB014accepted_content_types = ["text/html", "application/xhtml+xml"]015extract_links = true016extract_metadata = true017018# Storage settings019checkpoint_interval = 1000020compression = "gzip"
USAGE EXAMPLES
Basic Crawl
BASH001# Simple crawl with default settings002omnivore crawl https://example.com003004# Crawl with custom workers and depth005omnivore crawl https://example.com --workers 20 --depth 5006007# Crawl with output to file008omnivore crawl https://example.com --output results.json
Advanced Crawl
BASH001# Crawl with custom configuration002omnivore crawl https://example.com --config crawler.toml003004# Crawl with filtering005omnivore crawl https://example.com \006 --include-pattern "*/blog/*" \007 --exclude-pattern "*/admin/*"008009# Crawl with custom headers010omnivore crawl https://example.com \011 --header "Authorization: Bearer token" \012 --header "Accept-Language: en-US"
Programmatic Usage
RUST001use omnivore::{Crawler, CrawlerConfig};002003#[tokio::main]004async fn main() -> Result<(), Box<dyn std::error::Error>> {005 // Create crawler configuration006 let config = CrawlerConfig::builder()007 .workers(10)008 .max_depth(3)009 .politeness_delay(1000)010 .build();011012 // Initialize crawler013 let mut crawler = Crawler::new(config);014015 // Set callbacks016 crawler.on_page_crawled(|page| {017 println!("Crawled: {}", page.url);018 });019020 // Start crawling021 let results = crawler022 .crawl("https://example.com")023 .await?;024025 println!("Crawled {} pages", results.len());026 Ok(())027}
PERFORMANCE TUNING
Worker Optimization
The number of workers should be tuned based on your system resources and target sites:
- CPU-bound: Set workers to 2x CPU cores for optimal performance
- Network-bound: Can increase workers up to 100+ for slow sites
- Memory: Each worker consumes ~10-50MB depending on page size
BASH001# For CPU-bound processing (heavy parsing)002omnivore crawl https://example.com --workers 16003004# For network-bound crawling (slow sites)005omnivore crawl https://slow-site.com --workers 100006007# Memory-constrained environment008omnivore crawl https://example.com --workers 5 --max-page-size 1048576
BEST PRACTICES
Recommended Settings
- - Start with low workers (5-10) and increase gradually
- - Always respect robots.txt unless you have permission
- - Use appropriate delays (1-2 seconds minimum)
- - Set reasonable depth limits (3-5 for most sites)
- - Monitor memory usage and adjust workers accordingly
- - Use checkpointing for large crawls
- - Implement proper error handling and logging
TROUBLESHOOTING
Common Issues
High Memory Usage
BASH001# Reduce workers and page size002omnivore crawl https://example.com \003 --workers 5 \004 --max-page-size 1048576 \005 --frontier-size 10000
Slow Crawling
BASH001# Increase workers and reduce delays002omnivore crawl https://example.com \003 --workers 50 \004 --politeness-delay 500 \005 --timeout 10
Blocked by Site
BASH001# Use custom user agent and headers002omnivore crawl https://example.com \003 --user-agent "Mozilla/5.0..." \004 --header "Accept: text/html" \005 --crawl-delay 3000
Built with Rust. Developed by Pranav Karra