Databrew¶
Databrew turns a TOML file into a crawl that keeps a site's records current. You say which pages list the records and which fields to read; databrew fetches the pages, stores every new record and every later change to it, and picks up where it stopped when you run it again.
Install it with uv, on Python 3.14 or later:
uv tool install "databrew @ git+https://github.com/eyayaw/databrew"
Write a config for a practice bookstore:
name = "books"
start_urls = ["https://books.toscrape.com/catalogue/page-1.html"]
# Listing pages show 20 books, each in an article.product_pod card.
[listing.items]
selector = "article.product_pod"
[listing.items.fields]
url = { selector = "h3 a", attribute = "href" }
title = { selector = "h3 a", attribute = "title" }
price = { selector = ".price_color", parser = "parse_float" }
[listing.links]
items = "url" # the card field that links to the book's page
pagination = ["li.next a"] # the link to the next listing page
# Item pages show one book.
[item.items.fields]
title = ".product_main h1"
price = { selector = ".product_main .price_color", parser = "parse_float" }
availability = ".product_main .availability"
Run it, here capped at 20 requests:
$ databrew run books.toml -n 20
books: success, +19 new items, 20 observations, 0 failed URLs, traversal paused (Reached max requests limit (20))
total: 1 run, 0 failed, +19 new items, 20 observations, 0 failed URLs
The records are in data/books/, and the next run continues where this one stopped. The
tutorial walks through the same crawl step by step.
What you get¶
-
A history, not a snapshot
Each record is stored once, and again only when its content changes, so you can ask what a price was last month. Every card a listing page shows is kept too, as an observation.
-
Runs that resume
Stop a crawl with a request budget, a deadline, or Ctrl+C, and the next run continues the same queue without fetching completed pages again.
-
Cheap updates
After the first traversal, a run stops following pagination where it already has the records, and fetches known item pages again by age or when a watched field changes.
-
One verdict per run
Every run ends with a stop and an outcome that the exit code, the report, and the library call agree on. A crawl that a site blocks from the start fails, so a schedule notices.
Records land in Parquet or JSONL parts that DuckDB, pandas, and Polars read directly.
Where to go next¶
- Tutorial: crawl the bookstore and query the result.
- How-to guides: write a config, schedule runs, recover from failures, authenticate.
- Concepts: how a crawl walks a site, what it stores, and how a run ends.
- Reference: every config key, command, and Python call.
What databrew builds on¶
Databrew owns what happens between fetching and storing: the queue, retries, pacing, stop rules, revisits, and the run report. Three packages do the rest, and their docs are the reference for their part.
| Part | Package | Docs |
|---|---|---|
| Fetching, with HTTP clients or a browser | fetchkit | README |
| Selectors, JSON paths, and parsers | extractkit | Config, parsers |
| The record files | itemstore | README, format |