Documentation
¶
Overview ¶
Package ccrawl is a Go library for working with Common Crawl data: the collection list, the CDX URL index, WARC/WAT/WET archive files, the columnar Parquet index, CC-NEWS, and the host/domain ranks. It is the engine behind the ccrawl command line tool but is usable on its own.
Index ¶
- Constants
- Variables
- func BM25IDF(N, df int) float64
- func BM25TF(tf, dl int, avgDL float64, p BM25Params) float64
- func CDXNumPages(ctx context.Context, h *HTTPClient, crawlID string, q CDXQuery) (int, error)
- func CDXStream(ctx context.Context, h *HTTPClient, crawlID string, q CDXQuery, ...) error
- func CanonicalURL(raw string) string
- func ColumnarParquetURLs(ctx context.Context, h *HTTPClient, cache *Cache, crawlID, subset string, ...) ([]string, error)
- func ColumnarSource(crawlID, subset string, src Source) string
- func ComputeEdgeDegrees(ctx context.Context, h *HTTPClient, manifestURL string, nodeCount int64) (inDeg, outDeg []int32, err error)
- func ConfigDir() string
- func ContentSHA1(content []byte) string
- func CrawlScore(harmonicVal, changeRate float64) float64
- func CrawlTier(harmonicPos int64, changeRate float64) int
- func DecodeVarInt(b []byte) (uint64, int)
- func DiffCDX(ctx context.Context, urlsA, urlsB []string, crawlA, crawlB string, ...) error
- func DiffCDXSQL(urlsA, urlsB []string, crawlA, crawlB string) string
- func DocumentID(canonicalURL string) uint64
- func DownloadFiles(ctx context.Context, h *HTTPClient, src Source, paths []string, ...) error
- func DuckDBAvailable() bool
- func EncodeVarInt(v uint64) []byte
- func ExtractMarkdown(body []byte) (string, error)
- func ExtractOutLinks(htmlBytes []byte, baseURL string) []string
- func ExtractText(body []byte) string
- func ExtractTitle(body []byte) string
- func FetchPaths(ctx context.Context, h *HTTPClient, cache *Cache, crawlID, kind string) ([]string, error)
- func FileURL(path string, src Source) string
- func HTMLCanonicalURL(htmlBytes []byte) string
- func HTTPBody(block []byte) []byte
- func HTTPHeaders(block []byte) []byte
- func HTTPSURL(path string) string
- func HarmonicTier(harmonicPos int64, totalHosts int64) int
- func HostCDXAgg(ctx context.Context, parquetURLs []string, crawlID, host string, ...) error
- func HostCDXAggSQL(parquetURLs []string, crawlID, host string) string
- func HostCDXSingleSQL(parquetURLs []string, crawlID, host string) string
- func HostOf(raw string) string
- func InferMatchType(pattern string) (cleanURL, matchType string)
- func IterateWARC(r io.Reader, fn func(WARCRecord) error) error
- func IterateWAT(r io.Reader, crawlID string, fn func(WATRecord) error) error
- func IterateWET(r io.Reader, crawlID string, fn func(WETRecord) error) error
- func LibraryDir() string
- func LinkBoost(bm25Score, harmonicVal, alpha float64) float64
- func NormalizeURL(raw string) string
- func ParquetListLiteral(urls []string) string
- func RankStream(ctx context.Context, h *HTTPClient, url, tld string, fn func(Rank) error) error
- func ResolveCrawl(ctx context.Context, h *HTTPClient, cache *Cache, ref string) (string, error)
- func RunColumnarDuckDB(ctx context.Context, sql string, emit func(map[string]any) error) error
- func RunDuckDBJSON(ctx context.Context, dbPath, sql string, emit func(map[string]any) error) error
- func SURT(raw string) string
- func StreamPaths(ctx context.Context, h *HTTPClient, crawlID, kind string, ...) error
- func StripTrackingParams(rawQuery string) string
- func TierBoost(tier int) float64
- func TierInterval(tier int) int
- func Tokenize(text string) []string
- func VertexStream(ctx context.Context, h *HTTPClient, manifestURL string, ...) error
- func WriteWARCResponse(w io.Writer, rec NewWARCRecord) error
- type APIServer
- type BM25Params
- type CDXQuery
- type CDXRecord
- type Cache
- type ColumnarQuery
- type Config
- type Crawl
- type CrawlConfig
- type CrawlResult
- type DownloadResult
- type EdgeDegrees
- type ForwardDoc
- type ForwardIndexWriter
- type Frontier
- type FrontierEntry
- type HTTPClient
- func (h *HTTPClient) FetchBytes(ctx context.Context, url string) ([]byte, error)
- func (h *HTTPClient) Get(ctx context.Context, url string) (*http.Response, error)
- func (h *HTTPClient) GetDownload(ctx context.Context, url string) (*http.Response, error)
- func (h *HTTPClient) GetRange(ctx context.Context, url string, offset, length int64) (*http.Response, error)
- type HostCDXStats
- type HostDiffEntry
- type HostRecord
- type HostSchedule
- type HostStore
- type IndexReader
- type IndexSearchStore
- type InvertedIndexBuilder
- type Library
- type Location
- type MemHostStore
- type NewWARCRecord
- type NewsFile
- type ParquetWriter
- type PostingEntry
- type QualityResult
- type Rank
- type RobotsCache
- type RobotsEntry
- type RobotsRule
- type ScoredDoc
- type SearchResult
- type SearchStore
- type ServeConfig
- type Source
- type TextResult
- type VertexRecord
- type WARCHeader
- type WARCParquetRow
- type WARCRecord
- type WATLink
- type WATMeta
- type WATParquetRow
- type WATRecord
- type WETParquetRow
- type WETRecord
- type WebGraph
Constants ¶
const ( CollInfoURL = "https://index.commoncrawl.org/collinfo.json" DataBaseURL = "https://data.commoncrawl.org/" CDXBaseURL = "https://index.commoncrawl.org/" S3BaseURL = "s3://commoncrawl/" // ColumnarPrefix is the root of the columnar (Parquet) index. ColumnarPrefix = "cc-index/table/cc-main/warc/" // UserAgent identifies the client politely to Common Crawl's CDN. UserAgent = "ccrawl/1.0 (+https://github.com/tamnd/ccrawl-cli)" )
Common Crawl endpoints.
const ( DefaultTimeout = 120 * time.Second DefaultRetries = 5 DefaultDelay = 200 * time.Millisecond )
Defaults for the client and downloader.
const DuckDBPrelude = "INSTALL httpfs; LOAD httpfs; SET enable_progress_bar=false; SET allow_asterisks_in_http_paths=true;"
DuckDBPrelude is prepended to every statement ccrawl sends to the duckdb binary. httpfs reads remote Parquet over HTTPS or S3; the progress bar is noise on a pipe; and allow_asterisks_in_http_paths is required because the columnar index is addressed with a glob (subset=warc/*.parquet) over HTTP, which duckdb refuses by default.
Variables ¶
var DefaultBM25Params = BM25Params{K1: 1.2, B: 0.75}
DefaultBM25Params are the standard Okapi BM25 defaults.
var DefaultColumnarColumns = []string{
"url", "url_host_registered_domain", "fetch_status",
"content_mime_detected", "content_languages",
"warc_filename", "warc_record_offset", "warc_record_length",
}
DefaultColumnarColumns are the columns selected when none are given.
var DefaultCrawlConfig = CrawlConfig{ UserAgent: "CCrawl/2.0 (+https://ccrawl.tamnd.com/bot)", MaxRedirect: 5, Timeout: 120 * time.Second, }
DefaultCrawlConfig returns sensible defaults for the crawler.
var LocationColumns = []string{"url", "warc_filename", "warc_record_offset", "warc_record_length"}
LocationColumns return just the fields needed to range-fetch a record.
var PathKinds = []string{"warc", "wat", "wet", "robotstxt", "non200responses", "cc-index", "cc-index-table", "segment"}
PathKinds are the file manifests published per crawl.
Functions ¶
func BM25IDF ¶ added in v0.2.0
BM25IDF computes the IDF component for a term given N total docs and df doc frequency.
func BM25TF ¶ added in v0.2.0
func BM25TF(tf, dl int, avgDL float64, p BM25Params) float64
BM25TF computes the BM25 TF component.
func CDXNumPages ¶
CDXNumPages returns the number of result pages for a query.
func CDXStream ¶
func CDXStream(ctx context.Context, h *HTTPClient, crawlID string, q CDXQuery, fn func(CDXRecord) error) error
CDXStream runs a query and calls fn for each matching record, paginating through the server's pages and stopping at q.Limit.
func CanonicalURL ¶
CanonicalURL applies light canonicalization: ensure a scheme, lower-case the host, and drop a fragment. It does not reorder query parameters.
func ColumnarParquetURLs ¶
func ColumnarParquetURLs(ctx context.Context, h *HTTPClient, cache *Cache, crawlID, subset string, src Source) ([]string, error)
ColumnarParquetURLs resolves the columnar index glob into the explicit list of parquet file URLs for one crawl and subset. Common Crawl's bucket does not allow anonymous listing, so a duckdb run cannot expand the `*.parquet` glob over HTTPS (or anonymous S3) on its own. The crawl publishes the full file list in cc-index-table.paths.gz, so we read that manifest (cached) and turn each entry into a fetchable URL for the chosen source.
func ColumnarSource ¶
ColumnarSource returns the parquet glob for one crawl's columnar index subset (subset is warc, crawldiagnostics, or robotstxt).
func ComputeEdgeDegrees ¶ added in v0.2.0
func ComputeEdgeDegrees(ctx context.Context, h *HTTPClient, manifestURL string, nodeCount int64) (inDeg, outDeg []int32, err error)
ComputeEdgeDegrees streams all edge part files and computes in-degree and out-degree for every node. It requires knowing nodeCount (the total number of vertices) to allocate the degree arrays. Degrees are returned as two arrays indexed by node ID; the caller should join with vertex IDs.
func ContentSHA1 ¶ added in v0.2.0
ContentSHA1 returns the hex SHA-1 of raw content bytes (matches CC's digest field in CDX records).
func CrawlScore ¶ added in v0.2.0
CrawlScore computes a composite score combining link-graph importance and empirical change rate. Higher = higher crawl priority.
func CrawlTier ¶ added in v0.2.0
CrawlTier assigns a 1–5 crawl tier to a host based on its harmonic rank position and estimated change rate. Lower tier = more frequent crawling.
Tier 1: > 0.8 change rate + top 100 K rank → 24 h interval Tier 2: 0.5–0.8 + top 1 M → 3 days Tier 3: 0.2–0.5 + top 5 M → 7 days Tier 4: < 0.2 + top 10 M → 30 days Tier 5: everything else → on-demand
func DecodeVarInt ¶ added in v0.2.0
DecodeVarInt decodes a VByte-encoded integer from b, returning the value and the number of bytes consumed.
func DiffCDX ¶ added in v0.2.0
func DiffCDX(ctx context.Context, urlsA, urlsB []string, crawlA, crawlB string, fn func(HostDiffEntry) error) error
DiffCDX runs the differential CDX analysis via DuckDB and calls fn for each HostDiffEntry. Requires DuckDB on PATH.
func DiffCDXSQL ¶ added in v0.2.0
DiffCDXSQL returns the DuckDB SQL that computes per-host change rates between two crawl snapshots by joining on url and comparing content digests.
func DocumentID ¶ added in v0.2.0
DocumentID returns a stable 64-bit document ID for a canonical URL.
func DownloadFiles ¶
func DownloadFiles(ctx context.Context, h *HTTPClient, src Source, paths []string, localDir string, workers int, flat bool, progress func(DownloadResult)) error
DownloadFiles fetches a list of Common Crawl relative paths into localDir, concurrently and resumably. progress is called once per file when non-nil.
func DuckDBAvailable ¶
func DuckDBAvailable() bool
DuckDBAvailable reports whether a duckdb binary is on PATH.
func EncodeVarInt ¶ added in v0.2.0
EncodeVarInt encodes v as a VByte-encoded byte slice.
func ExtractMarkdown ¶
ExtractMarkdown converts an HTML document to a compact Markdown approximation. It is intentionally light: headings, paragraphs, list items, links, and emphasis, which covers the bulk of crawled article content.
func ExtractOutLinks ¶ added in v0.2.0
ExtractOutLinks extracts absolute URLs from HTML anchor hrefs, resolving relative URLs against baseURL.
func ExtractText ¶
ExtractText returns readable plain text from an HTML document, dropping the contents of script and style elements and collapsing whitespace.
func ExtractTitle ¶
ExtractTitle returns the <title> text of an HTML document.
func FetchPaths ¶
func FetchPaths(ctx context.Context, h *HTTPClient, cache *Cache, crawlID, kind string) ([]string, error)
FetchPaths downloads and decompresses a crawl's path manifest.
func FileURL ¶
FileURL turns a Common Crawl relative path into a fetchable URL for the given source. HTTPS uses the CloudFront mirror; S3 uses the bucket URI.
func HTMLCanonicalURL ¶ added in v0.2.0
HTMLCanonicalURL returns the best canonical URL from HTML headers (in priority order): link[rel=canonical], og:url. Returns "" if none found.
func HTTPBody ¶
HTTPBody splits a response block at the header/body boundary and returns the body. It returns the whole block when no boundary is found.
func HTTPHeaders ¶
HTTPHeaders returns the header section (status line + headers) of a response block, without the body.
func HTTPSURL ¶
HTTPSURL always returns the HTTPS mirror URL (used for control-plane fetches like manifests and collinfo regardless of the bulk source).
func HarmonicTier ¶ added in v0.2.0
HarmonicTier returns a 1–10 tier for a host's harmonic rank position (1 = most important, 10 = long tail). Used for multiplicative ranking boosts.
func HostCDXAgg ¶ added in v0.2.0
func HostCDXAgg(ctx context.Context, parquetURLs []string, crawlID, host string, fn func(HostCDXStats) error) error
HostCDXAgg runs the CDX aggregation for one or all hosts via DuckDB and calls fn for each result row. If host is non-empty, only that host is aggregated.
func HostCDXAggSQL ¶ added in v0.2.0
HostCDXAggSQL returns the DuckDB SQL to aggregate per-host CDX statistics from the columnar Parquet index for a given crawl. If host is non-empty the query filters to that host only; otherwise it aggregates all hosts (full table scan).
func HostCDXSingleSQL ¶ added in v0.2.0
HostCDXSingleSQL returns the DuckDB SQL to aggregate CDX stats for one host. This is faster than the full aggregation when only one host is needed.
func InferMatchType ¶
InferMatchType guesses the CDX matchType from a user-supplied URL pattern. "*.example.com" -> domain, "example.com/*" -> prefix, otherwise exact unless the caller already chose host/domain/prefix.
func IterateWARC ¶
func IterateWARC(r io.Reader, fn func(WARCRecord) error) error
IterateWARC reads a WARC file (a multi-member gzip stream where each member is one record) and calls fn for every record. The parser lives in pkg/warc.
func IterateWAT ¶
IterateWAT reads a WAT file and calls fn for each parsed record. The parser lives in pkg/wat.
func IterateWET ¶
IterateWET reads a WET file (WARC conversion records holding plain text) and calls fn for each record. The parser lives in pkg/wet.
func LibraryDir ¶
func LibraryDir() string
LibraryDir is the root of the structured dataset library that the --library flag downloads into and processes from. It is deliberately separate from the data dir: the data dir (see Config) holds ad-hoc downloads, the cache, and the local DuckDB file, while the library is a curated, browsable corpus you build up over time. CCRAWL_LIBRARY overrides the default of ~/notes/ccrawl.
func LinkBoost ¶ added in v0.2.0
LinkBoost blends a BM25 score with a host's harmonic centrality value. alpha controls the weight of the link signal (spec recommends 0.3).
func NormalizeURL ¶ added in v0.2.0
NormalizeURL applies light URL normalization: lowercase scheme+host, remove default port, strip fragment, strip known tracking parameters.
func ParquetListLiteral ¶
ParquetListLiteral renders parquet URLs as a duckdb list literal, e.g. ['https://a', 'https://b'], suitable as the argument to read_parquet.
func RankStream ¶ added in v0.2.0
RankStream streams every row of a gzipped rank table, calling fn for each entry. If tld is non-empty only hosts under that TLD are emitted. The caller controls early-exit by returning an error from fn.
func ResolveCrawl ¶
ResolveCrawl turns a loose reference into a canonical crawl ID.
"latest" -> newest crawl "CC-MAIN-2024-51" -> itself "2024-51" -> "CC-MAIN-2024-51" "2024" -> newest crawl whose ID starts with CC-MAIN-2024
func RunColumnarDuckDB ¶
RunColumnarDuckDB executes sql with the local duckdb binary, installing the httpfs extension for S3/HTTPS parquet access, and streams JSON rows to emit.
func RunDuckDBJSON ¶
RunDuckDBJSON runs sql with the local duckdb binary and streams JSON rows to emit. An empty dbPath runs against an in-memory database; a path opens (and creates) a persistent database file. httpfs is loaded so remote parquet over HTTPS or S3 works either way.
func SURT ¶
SURT converts a URL into a Sort-friendly URI Reordering Transform key, the canonical form Common Crawl uses to sort and group its index. For example "https://www.example.com/a/b?q=1" becomes "com,example,www)/a/b?q=1".
The transform lower-cases the scheme and host, reverses the host labels, drops a leading "www.", strips the default port, and keeps the path and query.
func StreamPaths ¶
func StreamPaths(ctx context.Context, h *HTTPClient, crawlID, kind string, fn func(string) error) error
StreamPaths streams a crawl's path manifest one path at a time.
func StripTrackingParams ¶ added in v0.2.0
StripTrackingParams removes known tracking query parameters from a raw URL query string. Returns the cleaned query string (without leading "?").
func TierBoost ¶ added in v0.2.0
TierBoost returns the multiplicative ranking boost for a harmonic tier. Tier 1 = 2.0×, tier 10 = 1.0×.
func TierInterval ¶ added in v0.2.0
TierInterval returns the recommended re-crawl interval in hours for a tier.
func Tokenize ¶ added in v0.2.0
Tokenize splits text into lowercase, stopword-filtered, min-2-char tokens.
func VertexStream ¶ added in v0.2.0
func VertexStream(ctx context.Context, h *HTTPClient, manifestURL string, fn func(VertexRecord) error) error
VertexStream downloads and streams all vertex part files listed in the manifest at manifestURL, calling fn for each record. Parts are fetched sequentially; use multiple goroutines externally for parallelism.
func WriteWARCResponse ¶ added in v0.2.0
func WriteWARCResponse(w io.Writer, rec NewWARCRecord) error
WriteWARCResponse writes a WARC/1.0 response record to w.
Types ¶
type APIServer ¶ added in v0.2.0
type APIServer struct {
// contains filtered or unexported fields
}
APIServer is the ccrawl v2 HTTP API server.
func NewAPIServer ¶ added in v0.2.0
func NewAPIServer(cfg ServeConfig, hosts HostStore, search SearchStore) *APIServer
NewAPIServer creates an API server with the given stores. Either store may be nil; endpoints that require the missing store return 503.
type BM25Params ¶ added in v0.2.0
type BM25Params struct {
K1 float64 // term frequency saturation (default 1.2)
B float64 // length normalization (default 0.75)
}
BM25Params holds the BM25 hyper-parameters.
type CDXQuery ¶
type CDXQuery struct {
URL string // URL or pattern
Match string // exact|prefix|host|domain (empty -> inferred from URL)
From string // 14-digit (or loose) lower time bound
To string // 14-digit (or loose) upper time bound
Status string // HTTP status filter (e.g. "200")
MIME string // mime-detected filter
Lang string // languages filter (ISO-639-3)
Filter []string
Limit int
}
CDXQuery describes a query against the CDX URL index.
type CDXRecord ¶
type CDXRecord struct {
CrawlID string `json:"crawl,omitempty" table:"crawl"`
URLKey string `json:"urlkey" table:"-"`
Timestamp string `json:"timestamp" table:"timestamp"` // 14-digit YYYYMMDDHHmmss
URL string `json:"url" table:"url,url"`
MIME string `json:"mime" table:"-"`
MIMEDetected string `json:"mime-detected" table:"mime"`
Status string `json:"status" table:"status"`
Digest string `json:"digest" table:"digest"`
Length string `json:"length" table:"length"`
Offset string `json:"offset" table:"offset"`
Filename string `json:"filename" table:"filename"`
Charset string `json:"charset,omitempty" table:"-"`
Languages string `json:"languages,omitempty" table:"languages"`
Truncated string `json:"truncated,omitempty" table:"-"`
Redirect string `json:"redirect,omitempty" table:"-"`
}
CDXRecord is one capture from the URL index. Numeric fields stay as strings because that is how the CDX server returns them; helpers convert on demand.
type Cache ¶
type Cache struct {
// contains filtered or unexported fields
}
Cache is a tiny on-disk blob cache keyed by an arbitrary string, with a TTL per entry. It is safe for the simple single-process use the CLI makes of it.
func NewCache ¶
NewCache returns a cache rooted under dir. If dir is empty or enabled is false, all operations are no-ops (cache miss on every Get).
type ColumnarQuery ¶
type ColumnarQuery struct {
Crawl string
Subset string // warc (default) | crawldiagnostics | robotstxt
Domain string // url_host_registered_domain
Host string // url_host_name
TLD string // url_host_tld
MIME string // content_mime_detected
Lang string // content_languages (substring match)
PathPrefix string // url_path prefix
Status int // fetch_status (0 = any)
Select []string
Limit int
}
ColumnarQuery builds SQL against the columnar (Parquet) index. The zero value selects everything; set fields to add WHERE clauses.
func (ColumnarQuery) SQL ¶
func (q ColumnarQuery) SQL(src Source) string
SQL renders the query as a runnable DuckDB statement reading parquet over the given source. The same text runs in Athena or Spark after swapping read_parquet for the engine's table reference.
type Config ¶
type Config struct {
DataDir string
CacheDir string
DBPath string
Source Source
Workers int
Timeout time.Duration
Delay time.Duration
Retries int
UserAgent string
CrawlID string
}
Config controls library behaviour. The zero value is not usable; call DefaultConfig and adjust.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config rooted at the XDG data/cache directories, with the most recent crawl resolved lazily (CrawlID == "latest").
func (Config) ParquetDir ¶
ParquetDir is where converted Parquet files land.
type Crawl ¶
type Crawl struct {
ID string `json:"id" kit:"id" table:"id"`
Name string `json:"name" table:"name"`
CDXAPI string `json:"cdx-api" table:"-"`
From string `json:"from,omitempty" table:"from"`
To string `json:"to,omitempty" table:"to"`
}
Crawl is one Common Crawl collection as published in collinfo.json.
func ListCrawls ¶
ListCrawls fetches and parses collinfo.json. Results are cached when a cache is supplied (pass nil to skip).
type CrawlConfig ¶ added in v0.2.0
CrawlConfig holds configuration for the crawler.
type CrawlResult ¶ added in v0.2.0
type CrawlResult struct {
URL string
FinalURL string // after redirects
Status int
ContentType string
Body []byte
Digest string // SHA-1 of body
FetchedAt time.Time
// Links extracted from HTML (relative links resolved to FinalURL)
Links []string
}
CrawlResult is the output of fetching a single URL.
func CrawlURL ¶ added in v0.2.0
func CrawlURL(ctx context.Context, rawURL string, cfg CrawlConfig) (*CrawlResult, error)
CrawlURL fetches a single URL and returns a CrawlResult. It does not consult the robots.txt cache; the caller must do that before calling CrawlURL.
type DownloadResult ¶
DownloadResult is the outcome of fetching one file.
type EdgeDegrees ¶ added in v0.2.0
type EdgeDegrees struct {
NodeID int64 `json:"node_id"`
InDegree int32 `json:"in_degree"`
OutDegree int32 `json:"out_degree"`
}
EdgeDegrees holds the in-degree and out-degree for one node.
type ForwardDoc ¶ added in v0.2.0
type ForwardDoc struct {
DocID uint64 `json:"doc_id" table:"doc_id"`
URL string `json:"url" table:"url"`
CanonURL string `json:"canon_url" table:"canon_url"`
Host string `json:"host" table:"host"`
Title string `json:"title" table:"title"`
Description string `json:"description" table:"description"`
Language string `json:"language" table:"language"`
WordCount int `json:"word_count" table:"word_count"`
LinkScore float32 `json:"link_score" table:"link_score"`
Snippet string `json:"snippet" table:"snippet"`
}
ForwardDoc is one row in the forward index.
type ForwardIndexWriter ¶ added in v0.2.0
type ForwardIndexWriter struct {
// contains filtered or unexported fields
}
ForwardIndexWriter appends ForwardDoc rows to a JSONL file.
func NewForwardIndexWriter ¶ added in v0.2.0
func NewForwardIndexWriter(path string) (*ForwardIndexWriter, error)
NewForwardIndexWriter opens (or creates) a JSONL forward index file.
func (*ForwardIndexWriter) Close ¶ added in v0.2.0
func (fw *ForwardIndexWriter) Close() error
Close flushes and closes the writer.
func (*ForwardIndexWriter) Write ¶ added in v0.2.0
func (fw *ForwardIndexWriter) Write(d ForwardDoc) error
Write appends one ForwardDoc to the index.
type Frontier ¶ added in v0.2.0
type Frontier struct {
// contains filtered or unexported fields
}
Frontier is an in-memory URL frontier with a priority heap and per-host politeness (minimum delay between requests to the same host).
func NewFrontier ¶ added in v0.2.0
NewFrontier creates a Frontier with the given per-host politeness delay.
func (*Frontier) Add ¶ added in v0.2.0
func (f *Frontier) Add(e FrontierEntry) bool
Add enqueues a URL if it has not been seen before. Returns true if added.
func (*Frontier) Pop ¶ added in v0.2.0
func (f *Frontier) Pop(now int64) (FrontierEntry, bool)
Pop removes and returns the highest-priority URL that is eligible to crawl now (host delay has elapsed). Returns false if no eligible URL exists.
To avoid starvation when the top-priority host is in its politeness window, Pop scans up to scanLimit candidates before giving up. Skipped (ineligible) entries are temporarily held and re-pushed so the heap remains consistent.
type FrontierEntry ¶ added in v0.2.0
type FrontierEntry struct {
URL string // normalized URL
Host string // hostname for politeness grouping
Priority float32 // harmonic centrality (higher = crawl sooner)
NextAt int64 // earliest Unix timestamp to fetch
Depth uint8 // BFS depth from seed
Retries uint8
}
FrontierEntry is one URL in the crawl frontier.
type HTTPClient ¶
type HTTPClient struct {
// contains filtered or unexported fields
}
HTTPClient is a polite, retrying HTTP client for Common Crawl. It rate-limits requests, retries on 429/5xx with linear backoff, and supports byte-range requests for single-record retrieval.
func NewHTTPClient ¶
func NewHTTPClient(cfg Config) *HTTPClient
NewHTTPClient builds an HTTPClient from cfg.
func (*HTTPClient) FetchBytes ¶
FetchBytes fetches url and returns the whole body.
func (*HTTPClient) GetDownload ¶
GetDownload fetches url with no client timeout (relies on ctx cancellation), for large archive bodies.
type HostCDXStats ¶ added in v0.2.0
type HostCDXStats struct {
Host string `json:"url_host_name"`
RegisteredDomain string `json:"registered_domain"`
URLCount int64 `json:"url_count"`
Status2xx int64 `json:"status_2xx"`
Status3xx int64 `json:"status_3xx"`
Status4xx int64 `json:"status_4xx"`
Status5xx int64 `json:"status_5xx"`
TopMIME string `json:"top_mime"`
Language string `json:"language"`
FirstSeen string `json:"first_seen"`
LastSeen string `json:"last_seen"`
TotalBytes int64 `json:"total_bytes"`
}
HostCDXStats is the CDX aggregation result for one host, produced by a DuckDB GROUP BY query over the columnar Parquet index.
type HostDiffEntry ¶ added in v0.2.0
type HostDiffEntry struct {
Host string `json:"host" table:"host"`
TotalURLs int64 `json:"total_urls" table:"total_urls"`
ChangedURLs int64 `json:"changed_urls" table:"changed_urls"`
ChangeRate float64 `json:"change_rate" table:"change_rate"`
Tier int `json:"tier" table:"tier"`
}
HostDiffEntry is one row of the per-host change report between two CDX snapshots. It shows how many URLs were seen in both crawls, how many had their content digest change, and the derived change rate.
type HostRecord ¶ added in v0.2.0
type HostRecord struct {
// Identity
Host string `json:"host" kit:"id" table:"host"`
HostRev string `json:"host_rev,omitempty" table:"-"`
TLD string `json:"tld" table:"tld"`
RegisteredDomain string `json:"registered_domain,omitempty" table:"registered_domain"`
// Rank signals (from rank table)
HarmonicPos int64 `json:"harmonic_pos" table:"harmonic_pos"`
HarmonicVal float64 `json:"harmonic_val" table:"harmonic_val"`
PageRankPos int64 `json:"pagerank_pos" table:"pagerank_pos"`
PageRankVal float64 `json:"pagerank_val" table:"pagerank_val"`
// Graph topology (from edge files)
InDegree int64 `json:"in_degree" table:"in_degree"`
OutDegree int64 `json:"out_degree" table:"out_degree"`
// CDX statistics (from columnar Parquet index)
URLCount int64 `json:"url_count" table:"url_count"`
Status2xx int64 `json:"status_2xx" table:"status_2xx"`
Status3xx int64 `json:"status_3xx" table:"status_3xx"`
Status4xx int64 `json:"status_4xx" table:"status_4xx"`
Status5xx int64 `json:"status_5xx" table:"status_5xx"`
TopMIME string `json:"top_mime,omitempty" table:"top_mime"`
Language string `json:"language,omitempty" table:"language"`
FirstSeen string `json:"first_seen,omitempty" table:"first_seen"`
LastSeen string `json:"last_seen,omitempty" table:"last_seen"`
TotalBytes int64 `json:"total_bytes" table:"total_bytes"`
}
HostRecord is the fully enriched profile for one host, combining signals from the web-graph rank table, graph topology (in/out-degree), and the CDX URL index.
func HostFromRank ¶ added in v0.2.0
func HostFromRank(r Rank) HostRecord
HostFromRank builds a minimal HostRecord from a Rank entry.
func HostLookupRank ¶ added in v0.2.0
func HostLookupRank(ctx context.Context, h *HTTPClient, rankURL, host string) (HostRecord, error)
HostLookupRank returns the rank-only HostRecord for a host by streaming the rank table. This is O(rank_table_size) — for a single-host lookup it is best to use HostLookupCDX for CDX stats and join separately.
type HostSchedule ¶ added in v0.2.0
type HostSchedule struct {
Host string `json:"host" table:"host"`
HarmonicPos int64 `json:"harmonic_pos" table:"harmonic_pos"`
HarmonicVal float64 `json:"harmonic_val" table:"harmonic_val"`
ChangeRate float64 `json:"change_rate" table:"change_rate"`
Tier int `json:"tier" table:"tier"`
IntervalH int `json:"interval_h" table:"interval_h"`
Score float64 `json:"score" table:"score"`
}
HostSchedule holds the crawl schedule for one host: its tier and derived priority score.
func HostScheduleFrom ¶ added in v0.2.0
func HostScheduleFrom(r Rank, changeRate float64) HostSchedule
HostScheduleFrom builds a HostSchedule from a Rank entry and a change rate.
type HostStore ¶ added in v0.2.0
type HostStore interface {
GetHost(ctx context.Context, host string) (*HostRecord, error)
TopHosts(ctx context.Context, n int, tld string) ([]HostRecord, error)
}
HostStore is the interface for host metadata lookups used by the API.
type IndexReader ¶ added in v0.2.0
IndexReader reads a flushed inverted index from disk.
func OpenIndex ¶ added in v0.2.0
func OpenIndex(dir string) (*IndexReader, error)
OpenIndex opens a flushed inverted index directory.
func (*IndexReader) Close ¶ added in v0.2.0
func (r *IndexReader) Close() error
Close releases the index file handles.
func (*IndexReader) Lookup ¶ added in v0.2.0
func (r *IndexReader) Lookup(term string) ([]PostingEntry, float64, bool)
Lookup returns the posting list for a term.
type IndexSearchStore ¶ added in v0.2.0
type IndexSearchStore struct {
// contains filtered or unexported fields
}
IndexSearchStore wraps an IndexReader to implement the SearchStore interface. The forward index is looked up from a map of docID → ForwardDoc.
func NewIndexSearchStore ¶ added in v0.2.0
func NewIndexSearchStore(idx *IndexReader, forward map[uint64]ForwardDoc) *IndexSearchStore
NewIndexSearchStore wraps an IndexReader.
func (*IndexSearchStore) Search ¶ added in v0.2.0
func (s *IndexSearchStore) Search(_ context.Context, query string, k int) ([]SearchResult, error)
Search tokenizes the query and returns top-k search results with snippets.
type InvertedIndexBuilder ¶ added in v0.2.0
type InvertedIndexBuilder struct {
N int // total docs indexed
TermCount int // unique term count (set by Flush)
// contains filtered or unexported fields
}
InvertedIndexBuilder accumulates (term → postings) in memory and writes the index to disk when Flush() is called.
func NewInvertedIndexBuilder ¶ added in v0.2.0
func NewInvertedIndexBuilder(dir string) (*InvertedIndexBuilder, error)
NewInvertedIndexBuilder creates a builder that writes to dir.
func (*InvertedIndexBuilder) Add ¶ added in v0.2.0
func (b *InvertedIndexBuilder) Add(docID uint64, tokens []string)
Add indexes a single document. DL (the document token length) is stored in each PostingEntry so BM25 scoring can use per-document length normalization.
func (*InvertedIndexBuilder) Flush ¶ added in v0.2.0
func (b *InvertedIndexBuilder) Flush() error
Flush writes the inverted index to disk in shard_NNN/ directories.
type Library ¶
Library is a structured corpus of Common Crawl archive files for one crawl, rooted at Root. The layout is predictable so a directory listing tells you exactly what you have:
<root>/<crawl>/<kind>/<file>.gz raw downloaded archives <root>/<crawl>/<format>/<kind>/<file>.<ext> processed output (parquet|jsonl)
Files are stored flat under each kind by their base name. A Common Crawl file name already encodes its segment and timestamp and is unique within a crawl, so the base name alone is a safe, stable key with no risk of collision.
func NewLibrary ¶
NewLibrary returns a Library rooted at root (or LibraryDir() when root is empty) for the given crawl ID.
func (Library) CrawlDir ¶
CrawlDir is the per-crawl root, the parent of every kind and format directory.
func (Library) ProcessedDir ¶
ProcessedDir is where processed output of a kind lives, grouped by format (parquet or jsonl) so the same archives can be materialised more than one way side by side.
type Location ¶
type Location struct {
Filename string `json:"filename" table:"filename"`
Offset int64 `json:"offset" table:"offset"`
Length int64 `json:"length" table:"length"`
URL string `json:"url,omitempty" table:"url,url"`
}
Location is the WARC file plus byte span needed to range-fetch this capture.
type MemHostStore ¶ added in v0.2.0
type MemHostStore struct {
// contains filtered or unexported fields
}
MemHostStore is a simple in-memory HostStore backed by a slice of HostRecord.
func NewMemHostStore ¶ added in v0.2.0
func NewMemHostStore(recs []HostRecord) *MemHostStore
NewMemHostStore builds a MemHostStore from a slice of HostRecord.
func (*MemHostStore) GetHost ¶ added in v0.2.0
func (s *MemHostStore) GetHost(_ context.Context, host string) (*HostRecord, error)
GetHost returns the HostRecord for a given hostname.
func (*MemHostStore) TopHosts ¶ added in v0.2.0
func (s *MemHostStore) TopHosts(_ context.Context, n int, tld string) ([]HostRecord, error)
TopHosts returns up to n hosts filtered optionally by TLD.
type NewWARCRecord ¶ added in v0.2.0
type NewWARCRecord struct {
TargetURI string
Date string
RecordID string
Block []byte // raw HTTP response bytes
}
NewWARCRecord holds the fields to write a fresh WARC response record.
type NewsFile ¶
type NewsFile struct {
Path string `json:"path" table:"path"`
Year int `json:"year" table:"year"`
Mon int `json:"month" table:"month"`
}
NewsFile describes one CC-NEWS WARC file.
func ListNewsFiles ¶
ListNewsFiles returns the CC-NEWS WARC files for a year and month. Pass month 0 to list every month of a year; pass year 0 to list everything found via the index page.
type ParquetWriter ¶
type ParquetWriter[T any] struct { // contains filtered or unexported fields }
ParquetWriter writes rows of type T to a zstd-compressed Parquet file.
func NewParquetWriter ¶
func NewParquetWriter[T any](path string) (*ParquetWriter[T], error)
NewParquetWriter creates a Parquet writer for path.
func (*ParquetWriter[T]) Close ¶
func (p *ParquetWriter[T]) Close() error
Close flushes and closes the file.
func (*ParquetWriter[T]) Rows ¶
func (p *ParquetWriter[T]) Rows() int64
Rows returns the number of rows written.
func (*ParquetWriter[T]) Write ¶
func (p *ParquetWriter[T]) Write(row T) error
Write appends one row.
type PostingEntry ¶ added in v0.2.0
type PostingEntry struct {
DocID uint64
TF uint32
DL uint32 // document token length at index time
}
PostingEntry is one (doc_id, term_freq, doc_len) triple in a posting list. DL is the document token length, stored per-posting so BM25 length normalization uses the actual document length rather than the corpus average.
type QualityResult ¶ added in v0.2.0
type QualityResult struct {
WordCount int
TitleLength int
HasMainContent bool
SpamScore float64 // 0–1
IsParked bool
IsShortContent bool // word_count < 50
}
QualityResult holds per-document quality signals computed from a TextResult.
func QualitySignals ¶ added in v0.2.0
func QualitySignals(tr TextResult) QualityResult
QualitySignals computes per-document quality signals from a TextResult.
type Rank ¶
type Rank struct {
Key string `json:"key" kit:"id" table:"key"` // host or domain (forward form)
HarmonicPos int64 `json:"harmonic_pos" table:"harmonic_pos"`
HarmonicVal float64 `json:"harmonic_val" table:"harmonic_val"`
PageRankPos int64 `json:"pagerank_pos" table:"pagerank_pos"`
PageRankVal float64 `json:"pagerank_val" table:"pagerank_val"`
}
Rank is a host/domain entry from the web-graph rank tables.
func RankLookup ¶
RankLookup streams a gzipped rank table from url and returns the entry whose reversed key matches the given host or domain, or a not-found error.
type RobotsCache ¶ added in v0.2.0
type RobotsCache struct {
// contains filtered or unexported fields
}
RobotsCache caches parsed robots.txt per host with a TTL.
func NewRobotsCache ¶ added in v0.2.0
func NewRobotsCache(ttl time.Duration, userAgent string) *RobotsCache
NewRobotsCache creates a cache with the given TTL and user-agent string.
func (*RobotsCache) Get ¶ added in v0.2.0
func (rc *RobotsCache) Get(host string) *RobotsEntry
Get returns the cached robots entry for host, or nil if not cached or expired.
func (*RobotsCache) Put ¶ added in v0.2.0
func (rc *RobotsCache) Put(host string, e *RobotsEntry)
Put stores a robots entry for host.
type RobotsEntry ¶ added in v0.2.0
type RobotsEntry struct {
Rules []RobotsRule
CrawlDelay time.Duration
ExpiresAt int64 // Unix timestamp
}
RobotsEntry is a cached robots.txt for one host.
func FetchRobots ¶ added in v0.2.0
func FetchRobots(ctx context.Context, h *HTTPClient, host, scheme string) *RobotsEntry
FetchRobots fetches and parses robots.txt for the given host. On timeout or 5xx, returns a permissive entry (allow all). On 404, returns allow all permanently. The caller should Put the result into the cache.
func (*RobotsEntry) IsAllowed ¶ added in v0.2.0
func (e *RobotsEntry) IsAllowed(path string) bool
IsAllowed reports whether the given path is allowed. The most specific (longest) matching rule wins, following the standard robots.txt precedence.
type RobotsRule ¶ added in v0.2.0
RobotsRule is one allow/disallow rule from robots.txt.
type SearchResult ¶ added in v0.2.0
type SearchResult struct {
DocID uint64 `json:"doc_id"`
URL string `json:"url"`
Host string `json:"host"`
Title string `json:"title"`
Snippet string `json:"snippet"`
Score float64 `json:"score"`
Language string `json:"language,omitempty"`
}
SearchResult is one search hit returned by the API.
type SearchStore ¶ added in v0.2.0
type SearchStore interface {
Search(ctx context.Context, query string, k int) ([]SearchResult, error)
}
SearchStore is the interface for full-text search used by the API.
type ServeConfig ¶ added in v0.2.0
type ServeConfig struct {
Addr string // e.g. ":8080"
DBPath string // path to DuckDB/SQLite host database (optional)
IndexDir string // path to the inverted index directory (optional)
}
ServeConfig holds configuration for the HTTP API server.
type TextResult ¶ added in v0.2.0
type TextResult struct {
Title string
Description string // <meta name="description">
CanonURL string // canonical URL from meta or link[rel=canonical]
Body string // extracted clean body text
WordCount int
Language string // BCP-47 code inferred from lang attribute
}
TextResult holds the output of HTML-to-text extraction.
func ExtractContent ¶ added in v0.2.0
func ExtractContent(htmlBytes []byte) TextResult
ExtractContent parses HTML bytes and returns a TextResult with clean text, title, description, canonical URL, and inferred language.
type VertexRecord ¶ added in v0.2.0
type VertexRecord struct {
ID int64 `json:"id" kit:"id" table:"id"`
HostRev string `json:"host_rev" table:"host_rev"`
Host string `json:"host" table:"host"`
}
VertexRecord is one row from the host vertices files: a numeric graph ID and the host name in reversed form (com.example.www).
type WARCParquetRow ¶
type WARCParquetRow struct {
RecordID string `parquet:"record_id,dict"`
CrawlID string `parquet:"crawl_id,dict"`
WARCType string `parquet:"warc_type,dict"`
TargetURI string `parquet:"target_uri"`
Date time.Time `parquet:"date,timestamp(microsecond)"`
IPAddress string `parquet:"ip_address,dict"`
PayloadDigest string `parquet:"payload_digest"`
ContentType string `parquet:"content_type,dict"`
ContentLength int64 `parquet:"content_length"`
Truncated string `parquet:"truncated,dict"`
HTTPStatus int32 `parquet:"http_status"`
HTTPMIME string `parquet:"http_mime,dict"`
WARCFilename string `parquet:"warc_filename,dict"`
WARCOffset int64 `parquet:"warc_offset"`
WARCLength int64 `parquet:"warc_length"`
Title string `parquet:"title"`
Language string `parquet:"language,dict"`
Markdown string `parquet:"markdown"`
Text string `parquet:"text"`
}
WARCParquetRow is the columnar schema for parsed WARC record metadata. When a response body is converted, the content fields are populated too.
type WARCRecord ¶
WARCRecord is a parsed WARC record: its header and the raw block bytes. For a response record the block is the full HTTP message (status line, headers, body).
func FetchWARCRecord ¶
func FetchWARCRecord(ctx context.Context, h *HTTPClient, filename string, offset, length int64) (WARCRecord, error)
FetchWARCRecord retrieves a single WARC record from the given file using a byte-range request. This is how a capture's content is pulled without downloading the whole multi-gigabyte WARC.
type WATLink ¶
WATLink is a hyperlink extracted from page HTML.
func ExtractLinks ¶
ExtractLinks returns the outbound hyperlinks of an HTML document, resolved against base when possible.
type WATParquetRow ¶
type WATParquetRow struct {
RecordID string `parquet:"record_id,dict"`
CrawlID string `parquet:"crawl_id,dict"`
URL string `parquet:"url"`
Date time.Time `parquet:"date,timestamp(microsecond)"`
HTTPStatus int32 `parquet:"http_status"`
ContentType string `parquet:"content_type,dict"`
Title string `parquet:"title"`
LinksCount int32 `parquet:"links_count"`
Links string `parquet:"links"` // JSON
Metas string `parquet:"metas"` // JSON
}
WATParquetRow is the columnar schema for WAT link and metadata records.
type WETParquetRow ¶
type WETParquetRow struct {
RecordID string `parquet:"record_id,dict"`
CrawlID string `parquet:"crawl_id,dict"`
URL string `parquet:"url"`
Date time.Time `parquet:"date,timestamp(microsecond)"`
ContentLanguage string `parquet:"content_language,dict"`
TextLength int32 `parquet:"text_length"`
Text string `parquet:"text"`
}
WETParquetRow is the columnar schema for WET plain-text records.
type WebGraph ¶ added in v0.2.0
type WebGraph struct {
ID string // e.g. cc-main-2026-mar-apr-may
BaseURL string // https://data.commoncrawl.org/projects/hyperlinkgraph/{ID}/
HostNodes int64
HostArcs int64
Published string
}
WebGraph describes one Common Crawl web-graph release.
func LatestWebGraph ¶ added in v0.2.0
LatestWebGraph fetches the CC web-graphs index page and returns the most recent host-level graph release. Results are cached for 24 hours.
func (WebGraph) HostEdgesManifestURL ¶ added in v0.2.0
HostEdgesManifestURL is the manifest listing edge part files.
func (WebGraph) HostRankURL ¶ added in v0.2.0
HostRankURL is the single gzipped rank table for hosts.
func (WebGraph) HostVerticesManifestURL ¶ added in v0.2.0
HostVerticesManifestURL is the manifest listing vertex part files.