Chronicle
The web scraping library that remembers.
Chronicle is a data-science-native web scraping framework with temporal versioning and drift detection built in. Every scrape is stored, profiled, and compared to history — so you know exactly when your data changes and why.
Why Chronicle?
Existing scraping libraries hand you raw data and walk away. Chronicle remembers.
| Tool | Strength | The gap Chronicle fills |
|---|---|---|
| Requests | HTTP requests | No parsing, no structure |
| BeautifulSoup | HTML parsing | No fetching, no data quality |
| Scrapy | Large-scale crawling | No drift detection, no reproducibility |
| Selenium | JS-rendered pages | No data pipeline, no versioning |
| lxml | Fast parsing | No fetching, no schema |
Chronicle sits on top of these tools and adds the layer data scientists actually need:
- 🕐 Temporal versioning — every scrape is stored, versioned, and replayable
- 🔍 Drift detection — catch broken selectors before they poison your pipeline
- 📊 DataFrame-native — one line from URL to analysis-ready data
- 📜 Reproducible — every run produces a self-contained artifact
- ✅ Schema validation — data quality enforced at scrape time
- 🧠 DS-first design — built for Jupyter, pandas, and real pipelines
Install
pip install chronicle-ds
Chronicle requires Python 3.10+.
Quickstart
from chronicle import Scrape
df = Scrape("https://example.com/products").to_dataframe()
print(df.head())
Note on auto-detection: The one-liner works best on pages with HTML
<table>elements or simple repeated list structures. It can pick the wrong structure on pages with navigation chrome (news sites, SPAs). For those, passselectors={...}— see "More Control" below.
More Control
from chronicle import Scrape
df = Scrape(
url="https://example.com/products",
selectors={
"_container": "div.product",
"name": "h2",
"price": "span.price",
"rating": "span.rating",
},
pages=5,
rate_limit=2.0,
).to_dataframe()
The Core Idea
Chronicle treats every scrape as a versioned event. This unlocks two things no other scraping library provides:
1. Temporal Versioning
Every run is stored with:
- Raw HTML
- Parsed data (Parquet)
- Statistical profile
- Run metadata (timestamps, config, library version)
# Query the full history of a scraper
history = Scrape.history("https://example.com/products")
history.drift_timeline()
2. Drift Detection
Chronicle compares each new run against a baseline and detects:
- Schema drift — columns added, removed, or renamed
- Null drift — fields suddenly returning
None - Distribution drift — mean, median, or variance shifts
- Range drift — values outside historical bounds
- Selector health — selectors returning zero elements
result = Scrape("https://example.com/products").run()
if result.drift_detected:
print(result.drift_report())
# ⚠️ price null% jumped from 0.02 → 0.98 (selector likely broken)
Status
🚧 Early development. v0.1.0 in progress.
What's built
- HTTP layer (
fetch.py) — retries, rate limiting, caching - HTML parsing (
parse.py) — selector + auto table/list detection - Schema validation (
normalize.py) — pydantic + quality reports -
Scrapeclass (core.py) — one-line API - Storage + versioning (
storage.py) — versioned artifacts + SQLite - Profile generation (
profile.py) — statistical fingerprints - Drift detection (
drift.py) — null / distribution / range / schema - CLI (
cli.py) — version, scrape, runs commands - 18 passing unit tests
- Published to PyPI as
chronicle-ds
Roadmap
- Data contracts (schema + quality guarantees)
- Reproducibility artifacts
- Self-healing selectors
- Playwright support for JS-rendered pages
- CLI + recipe system
Contributing
Chronicle is in early, fast-moving development. Issues, ideas, and PRs are welcome.
git clone git@github.com:TheDataNormad/chronicle.git
cd chronicle
python -m venv .venv
source .venv/Scripts/activate # Windows
pip install -e ".[dev]"
pytest
License
MIT — see LICENSE.
Author
Built by @TheDataNormad.
Metadata
Release files for chronicle-ds 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| chronicle_ds-0.1.2.tar.gz | 22.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chronicle_ds-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.7 kB
Release files / chronicle_ds-0.1.2.tar.gz
| Download URL | chronicle_ds-0.1.2.tar.gz |
|---|---|
| Size | 22.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
642691dd6f7b8b7f6eaddaee3c4fe492e1cf9a3a7fc96c744649d07fa61723f6
|
|
BLAKE2b-256 checksum How to use checksums |
ed99833e79324d5fe722724060578d0c2f037fc9466d1aa500f5284cb357cce1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / chronicle_ds-0.1.2-py3-none-any.whl
| Download URL | chronicle_ds-0.1.2-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
30b074c01ad743d0913fb0985b8a5ed3876a7b24f3bd325fcf6cbd3a3dfd0b84
|
|
BLAKE2b-256 checksum How to use checksums |
27a3dc48473694d588048c1586bb461c00e374d5a314e0665e493a525b10be6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|