crawler

package
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package crawler implements a concurrent website crawler with rate limiting, depth control, URL deduplication, and robots.txt compliance.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FetchSitemapURLs

func FetchSitemapURLs(ctx context.Context, client *http.Client, sitemapURLs []string) []string

FetchSitemapURLs fetches and parses sitemap(s) from the given URLs. Supports both sitemap index files and direct URL sets.

func ParseHTMLDoc added in v0.1.1

func ParseHTMLDoc(pageURL string, body []byte) (*html.Node, []Link, []Form, error)

ParseHTMLDoc parses the body once and returns the doc along with links/forms. Use this when you need to keep the parsed doc for later use by checks.

func ResolveURL added in v0.1.1

func ResolveURL(base, href string) string

ResolveURL resolves a reference URL against a base URL and returns the absolute form. Returns an empty string for fragment-only, mailto:, or javascript: references, or if either URL fails to parse.

func ServeDir

func ServeDir(ctx context.Context, dir string) (*http.Server, string, error)

ServeDir starts a temporary HTTP file server for the given directory. Returns the server and its address (host:port). The caller must call srv.Close() when done.

Types

type CircuitBreakerRegistry added in v0.1.1

type CircuitBreakerRegistry struct {
	// contains filtered or unexported fields
}

CircuitBreakerRegistry manages per-host circuit breakers. It is safe for concurrent use.

func NewCircuitBreakerRegistry added in v0.1.1

func NewCircuitBreakerRegistry(threshold int, cooldown time.Duration) *CircuitBreakerRegistry

NewCircuitBreakerRegistry creates a registry with the given failure threshold and cooldown duration. When threshold consecutive failures are recorded for a host, the circuit opens. After cooldown elapses the circuit half-opens to allow a single probe request.

func (*CircuitBreakerRegistry) AllowRequest added in v0.1.1

func (r *CircuitBreakerRegistry) AllowRequest(host string) bool

AllowRequest reports whether a request to the given host should be allowed. The host is typically the hostname portion of a URL (e.g. "example.com").

func (*CircuitBreakerRegistry) RecordFailure added in v0.1.1

func (r *CircuitBreakerRegistry) RecordFailure(host string)

RecordFailure records a failure for the given host.

func (*CircuitBreakerRegistry) RecordSuccess added in v0.1.1

func (r *CircuitBreakerRegistry) RecordSuccess(host string)

RecordSuccess records a successful response for the given host, resetting the failure count and closing the circuit.

type CircuitState added in v0.1.1

type CircuitState int

CircuitState represents the state of a per-host circuit breaker.

const (
	// CircuitClosed is the normal operating state; requests are allowed.
	CircuitClosed CircuitState = iota
	// CircuitOpen means the host has exceeded the failure threshold; requests are blocked.
	CircuitOpen
	// CircuitHalfOpen allows a single probe request through to test if the host has recovered.
	CircuitHalfOpen
)

type Config

type Config struct {
	MaxDepth        int
	Concurrency     int
	Timeout         time.Duration
	PageTimeout     time.Duration
	RateLimit       int
	RetryAttempts   int
	RetryDelay      time.Duration
	UserAgent       string
	FollowRedirects int
	RespectRobots   bool
	Exclude         []string
	AuthHeader      string
	AuthValue       string
	CookieJar       http.CookieJar
	AllowPrivateIPs bool // When true, skip SSRF protection for private IPs
	Logger          *slog.Logger
	MaxPages        int // Maximum number of pages to crawl; 0 means no limit

	// CircuitBreaker, when non-nil, gates requests per host. If a host has
	// accumulated too many consecutive failures the breaker opens and the
	// crawler skips further requests to that host until the cooldown expires.
	CircuitBreaker *CircuitBreakerRegistry

	// Fetcher, when non-nil, overrides the default HTTP page retrieval. It is
	// used to plug in a headless-browser fetcher that renders JavaScript. SSRF
	// validation, rate limiting, retries, and the circuit breaker still run in
	// front of the fetcher.
	Fetcher Fetcher
}

Config controls crawler behavior.

type Crawler

type Crawler struct {
	// contains filtered or unexported fields
}

Crawler performs concurrent crawling with rate limiting.

func New

func New(cfg Config) *Crawler

New creates a configured Crawler.

func (*Crawler) Crawl

func (c *Crawler) Crawl(ctx context.Context, startURL string) ([]*Page, error)

Crawl starts from the given URL and discovers pages up to MaxDepth. Returns all crawled pages. Safe for concurrent use via internal locking.

type Fetcher added in v0.1.1

type Fetcher interface {
	Fetch(ctx context.Context, page *Page, targetURL string) error
}

Fetcher retrieves a single page's content, populating the provided Page (StatusCode, Headers, Body, Links, Forms, Doc). The default implementation is the crawler's built-in HTTP fetch; a headless-browser implementation can be supplied via Config.Fetcher to analyze JavaScript-rendered pages.

type Form

type Form struct {
	Action  string
	Method  string
	ID      string
	Inputs  []FormInput
	HasCSRF bool
}

Form represents an HTML form found on a page.

type FormInput

type FormInput struct {
	Name     string
	Type     string
	Required bool
	Value    string
}

FormInput represents a form field.

type HostCircuitBreaker added in v0.1.1

type HostCircuitBreaker struct {
	// contains filtered or unexported fields
}

HostCircuitBreaker tracks consecutive failures for a single host and automatically opens the circuit when the threshold is reached, closing it again after a cooldown period.

func (*HostCircuitBreaker) AllowRequest added in v0.1.1

func (b *HostCircuitBreaker) AllowRequest() bool

AllowRequest reports whether a request to this host should be allowed. It transitions from Open to HalfOpen when the cooldown has elapsed.

func (*HostCircuitBreaker) RecordFailure added in v0.1.1

func (b *HostCircuitBreaker) RecordFailure()

RecordFailure increments the consecutive failure count and may open the circuit.

func (*HostCircuitBreaker) RecordSuccess added in v0.1.1

func (b *HostCircuitBreaker) RecordSuccess()

RecordSuccess resets the failure count and closes the circuit.

func (*HostCircuitBreaker) State added in v0.1.1

func (b *HostCircuitBreaker) State() CircuitState

State returns the current circuit state (for testing/diagnostics).

type Link struct {
	Href     string
	Text     string
	Rel      string
	External bool
	Anchor   bool
	Resource bool   // true for non-anchor resource URLs (img, script, iframe, etc.)
	Tag      string // source element tag (e.g., "img", "script", "iframe")
}

Link represents a hyperlink found on a page.

type Page

type Page struct {
	URL          string
	StatusCode   int
	Headers      http.Header
	Body         []byte
	Links        []Link
	Forms        []Form
	Depth        int
	ParentURL    string
	Duration     time.Duration
	Error        error
	AuthRequired bool       // true when server returned 401/403
	Doc          *html.Node // parsed HTML tree, populated once during fetch
}

Page represents a single crawled page with its metadata.

type ParseResult added in v0.1.1

type ParseResult struct {
	Links    []Link
	Forms    []Form
	ParseErr error // non-nil if HTML parsing encountered an error (partial results still returned)
}

ParseResult holds links/forms extraction results along with any parse error.

func ParseHTML added in v0.1.1

func ParseHTML(pageURL string, body []byte) ParseResult

ParseHTML extracts links and forms, returning partial results even on parse error.

type RobotsCache

type RobotsCache struct {
	// contains filtered or unexported fields
}

RobotsCache caches parsed robots.txt rules per host.

func NewRobotsCache

func NewRobotsCache() *RobotsCache

NewRobotsCache creates an empty robots.txt cache.

func (*RobotsCache) Allowed

func (rc *RobotsCache) Allowed(rawURL, userAgent string) bool

Allowed checks if a URL is permitted by robots.txt rules. Bot-specific user-agent sections are matched first (case-insensitive), then the wildcard (*) section is used as fallback. If both bot-specific and wildcard rules exist, a path is disallowed if either section blocks it.

func (*RobotsCache) CrawlDelay added in v0.1.1

func (rc *RobotsCache) CrawlDelay(origin, userAgent string) time.Duration

CrawlDelay returns the crawl-delay directive for the given origin and user-agent, or 0 if not set. Bot-specific sections are matched first, then wildcard.

func (*RobotsCache) Fetch

func (rc *RobotsCache) Fetch(ctx context.Context, client *http.Client, origin string)

Fetch downloads and parses robots.txt for the given origin.

func (*RobotsCache) Sitemaps

func (rc *RobotsCache) Sitemaps(origin string) []string

Sitemaps returns sitemap URLs declared in robots.txt.

type SitemapURL

type SitemapURL struct {
	Loc        string `xml:"loc"`
	Lastmod    string `xml:"lastmod,omitempty"`
	Changefreq string `xml:"changefreq,omitempty"`
	Priority   string `xml:"priority,omitempty"`
}

SitemapURL represents a single URL entry in a sitemap.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL