Skip to main content

Crawler

Struct Crawler 

Source
pub struct Crawler<B, W> { /* private fields */ }
Expand description

Crawls requests from a Frontier with a Backend and a Worker.

run pops seeds from the frontier and handles up to with_concurrency of them at once. Each one gets its own client from the backend and is handed to the worker, whose Outcome is reported back to the frontier.

The run ends once the frontier is empty and no request is in flight, when a worker returns Outcome::Stop, the request or time budget is spent, or the shutdown_token is cancelled. Stopping lets requests in flight finish, for at most the shutdown grace period if one is set.

Politeness is per host: with_host_concurrency and with_host_delay limit how hard a single host is crawled, and with the robots feature, with_robots obeys robots.txt.

§Examples

use std::time::Duration;

use spire_core::backend::Noop;
use spire_core::frontier::FrontierExt;
use spire_core::frontier::memory::InMemFrontier;
use spire_core::frontier::seed::Seed;
use spire_core::worker::from_fn;
use spire_core::{Context, Crawler, Result};

async fn handle(cx: Context<Noop>) -> Result<()> {
    cx.queue().follow("https://example.com/next").await?;
    Ok(())
}

let crawler = Crawler::new(Noop, from_fn(handle))
    .with_frontier(InMemFrontier::fifo().dedup().allow_hosts(["example.com"]))
    .with_max_requests(100)
    .with_host_concurrency(2)
    .with_request_timeout(Duration::from_secs(30))
    .with_seed(Seed::get("https://example.com/")?);

let stats = crawler.run().await?;
assert_eq!(stats.requests, 2);

Implementations§

Source§

impl<B, W> Crawler<B, W>
where B: Backend, W: Worker<B::Client>,

Source

pub async fn run(&self) -> Result<Stats>

Crawls until the frontier is empty and no request is in flight, a worker returns Outcome::Stop, the budget is spent, or the run is shut down.

§Errors

Returns an error if a seed cannot be pushed, or if the frontier fails mid-run; requests in flight are drained first.

Source§

impl<B, W> Crawler<B, W>

Source

pub fn new(backend: B, worker: W) -> Self

Creates a crawler with an InMemFrontier::fifo frontier that retries with the default RetryPolicy, no datasets, a concurrency of 8 and no limits.

Source

pub fn with_frontier(self, frontier: impl Frontier) -> Self

Replaces the frontier.

Seeds added with with_seed are pushed when the run starts, so they go to the new frontier.

Source

pub fn with_dataset<T, D>(self, dataset: D) -> Self
where T: Send + 'static, D: Dataset<T>,

Registers dataset for items of type T, replacing any previous one.

Source

pub fn with_concurrency(self, limit: usize) -> Self

Sets how many requests are handled at once, at least one.

Source

pub const fn with_max_requests(self, max: usize) -> Self

Stops the run after starting max requests, counting every attempt.

Source

pub const fn with_time_limit(self, limit: Duration) -> Self

Stops the run once it has lasted limit.

Source

pub const fn with_request_timeout(self, timeout: Duration) -> Self

Fails a request that takes longer than timeout to handle, fetching included. Timed out requests are retried.

Source

pub const fn with_shutdown_grace(self, grace: Duration) -> Self

Cancels requests still in flight grace after the run starts stopping, instead of waiting for them indefinitely.

Cancelled requests are reported to the frontier as Report::Cancelled.

Source

pub fn with_host_concurrency(self, limit: usize) -> Self

Sets how many requests to the same host are in flight at once, at least one. Unlimited by default.

Source

pub const fn with_host_delay(self, delay: Duration) -> Self

Waits at least delay between starting two requests to the same host.

Source

pub fn with_robots(self, robots: impl Into<Robots>) -> Self

Available on crate feature robots only.

Obeys robots.txt: fetches each origin’s file before crawling it, skips what it disallows, and honours its Crawl-delay.

Takes a user agent, or a Robots to fetch with another backend or change how long rules are kept; see Robots for how failures are handled. Disallowed requests are reported as Report::Skipped.

use spire_core::backend::Noop;
use spire_core::crawler::Robots;
use spire_core::worker::from_fn;
use spire_core::{Context, Crawler};

let worker = from_fn(|_: Context<Noop>| async {});
let crawler = Crawler::new(Noop, worker).with_robots("MyBot");

// robots.txt through another backend, e.g. HTTP for a browser crawl.
let worker = from_fn(|_: Context<Noop>| async {});
let crawler = Crawler::new(Noop, worker).with_robots(Robots::new("MyBot").with_backend(Noop));
Source

pub fn with_seed(self, seed: Seed) -> Self

Adds a seed to push when the run starts.

Source

pub fn with_seeds(self, seeds: impl IntoIterator<Item = Seed>) -> Self

Adds seeds to push when the run starts.

Source

pub fn backend(&self) -> &B

Returns the backend, e.g. to shut it down after a run.

Source

pub fn queue(&self) -> Queue

Returns a queue for adding seeds to the frontier.

Source

pub fn dataset<T: Send + 'static>(&self) -> Result<Data<T>>

Returns the dataset for items of type T.

§Errors

Returns a Dataset error if no dataset is registered for T.

Source

pub fn snapshot(&self) -> Option<Vec<Seed>>

Returns a copy of every seed the frontier holds, see Frontier::snapshot. After a stopped run it includes the requests cancelled or never started.

Source

pub fn stats(&self) -> Stats

Returns the stats of the current run while it runs, or of the last one.

Source

pub fn shutdown_token(&self) -> CancellationToken

Returns a token that stops the run when cancelled.

Requests in flight finish; nothing new starts.

Trait Implementations§

Source§

impl<B, W> Debug for Crawler<B, W>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<B, W> !Freeze for Crawler<B, W>

§

impl<B, W> !RefUnwindSafe for Crawler<B, W>

§

impl<B, W> !UnwindSafe for Crawler<B, W>

§

impl<B, W> Send for Crawler<B, W>
where Arc<B>: Send, Arc<W>: Send,

§

impl<B, W> Sync for Crawler<B, W>
where Arc<B>: Sync, Arc<W>: Sync,

§

impl<B, W> Unpin for Crawler<B, W>
where Arc<B>: Unpin, Arc<W>: Unpin,

§

impl<B, W> UnsafeUnpin for Crawler<B, W>
where Arc<B>: UnsafeUnpin, Arc<W>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more