LLM-ready batch crawling for Nordic company data
Project description
NordCrawl
LLM-ready batch crawling for Nordic company data.
NordCrawl crawls URL lists from CSV/JSON, extracts structured Swedish company data, and can upsert the results directly into Supabase.
Live demo
The screenshot above is based on a real crawl run with Rich output.
- Demo input:
examples/urls.json - Verified output:
examples/results.json - More details:
examples/README.md
Why people star projects like this
- Fast to try: one command from file or CLI
- Useful immediately: real data extraction for Swedish company pages
- Practical output: JSON, CSV, and Supabase sync
- Production-minded: retries, dedupe, rate limiting, and validation
Features
- Batch crawling with configurable concurrency
- Per-domain rate limiting
- Retry logic with exponential backoff
- Swedish company data extraction
- company name
- org number
- phone
- address
- Consistent JSON schema via Pydantic
- CSV/JSON import and export
- Supabase upserts with dedupe by URL
- CLI-first workflow with a clean Python API
PyPI
The package name is nordcrawl.
After publishing, install it with:
pip install nordcrawl
Quick start
1) Install dependencies
pip install -r requirements.txt
2) Configure environment
Copy the example file and fill in your Supabase keys:
cp .env.example .env
3) Run a crawl
python3 main.py crawl-urls \
https://www.ikea.com/se/sv/ \
https://www.hemkop.se/ \
https://www.ica.se/ \
--output results.json
CLI
Crawl from file
python3 main.py crawl data/test_urls.json --output results.json --format json
Save directly to Supabase
python3 main.py crawl data/test_urls.json --save-db
Show stats
python3 main.py stats --limit 50
Search stored companies
python3 main.py search "IKEA" --limit 20
Export from Supabase
python3 main.py export company_data.csv --format csv
Python API
import asyncio
from src import BatchCrawler, SupabaseManager
async def main() -> None:
crawler = BatchCrawler(max_concurrent=5, rate_limit_delay=2.0)
results = await crawler.crawl_urls([
"https://www.ikea.com/se/sv/",
"https://www.hemkop.se/",
"https://www.ica.se/",
])
print(results)
asyncio.run(main())
Input formats
CSV
url
https://www.example.se
https://www.example2.se
JSON
[
"https://www.example.se",
{"url": "https://www.example2.se"}
]
Supabase table
NordCrawl expects a table named company_data with these columns:
urlcompany_nameorg_numberemailphoneaddresspostal_codecitywebsitecrawled_atstatusraw_html_hashextraction_confidencecreated_atupdated_at
The migration is included here:
supabase/migrations/20240325000001_create_company_data_table.sql
Example output
{
"url": "https://www.example.se",
"company_name": "Exempel AB",
"org_number": "556123-4567",
"email": "info@example.se",
"phone": "+46701234567",
"address": "Storgatan 1",
"postal_code": "123 45",
"city": "Stockholm",
"status": "completed",
"extraction_confidence": 0.85
}
Docker / Supabase note
Local supabase start requires Docker access. If you do not want to run Supabase locally:
- Apply the migration in your remote Supabase project.
- Set
SUPABASE_URLandSUPABASE_KEYin.env. - Run the crawler with
--save-db.
Project structure
.
├── main.py
├── requirements.txt
├── src/
│ ├── api/
│ ├── crawlers/
│ ├── database/
│ ├── extractors/
│ └── models/
├── supabase/
│ └── migrations/
└── tests/
Roadmap
- Better selector coverage for Swedish business websites
- Richer address parsing
- Supabase auth-aware dashboard
- Web UI for crawl jobs
- More sample datasets and benchmarks
Contributing
PRs are welcome.
- Fork the repo
- Create a branch
- Add tests
- Open a pull request
License
Apache-2.0
If you like the project, star it on GitHub to help it grow.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nordcrawl-0.1.1.tar.gz.
File metadata
- Download URL: nordcrawl-0.1.1.tar.gz
- Upload date:
- Size: 27.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
467441a2b5fb940c11a7268e438f2234d27a5228104b119995c0aeb7455e0151
|
|
| MD5 |
7819f0fd1cf7745ea4d503b6f4d6909b
|
|
| BLAKE2b-256 |
d66ea28517dd0603dec2ab4989819df88b64df8574047d413aef8f24749b2f42
|
Provenance
The following attestation bundles were made for nordcrawl-0.1.1.tar.gz:
Publisher:
pypi-publish.yml on cedendahlkim/nordcrawl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nordcrawl-0.1.1.tar.gz -
Subject digest:
467441a2b5fb940c11a7268e438f2234d27a5228104b119995c0aeb7455e0151 - Sigstore transparency entry: 1180095416
- Sigstore integration time:
-
Permalink:
cedendahlkim/nordcrawl@32a6aa4cb087ae97e2d62ca8675cb7448caacb44 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/cedendahlkim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@32a6aa4cb087ae97e2d62ca8675cb7448caacb44 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nordcrawl-0.1.1-py3-none-any.whl.
File metadata
- Download URL: nordcrawl-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cc0dd59ceff03eaca5e17225ccd5fbaee0ad839e0551a4cabadf4df5a2d412f
|
|
| MD5 |
25ec269235789a825d07e0980db371b7
|
|
| BLAKE2b-256 |
317ca25f380fe778c5e437da9a97c8279a7f42cc6319feca50fabef570a2d971
|
Provenance
The following attestation bundles were made for nordcrawl-0.1.1-py3-none-any.whl:
Publisher:
pypi-publish.yml on cedendahlkim/nordcrawl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nordcrawl-0.1.1-py3-none-any.whl -
Subject digest:
9cc0dd59ceff03eaca5e17225ccd5fbaee0ad839e0551a4cabadf4df5a2d412f - Sigstore transparency entry: 1180095439
- Sigstore integration time:
-
Permalink:
cedendahlkim/nordcrawl@32a6aa4cb087ae97e2d62ca8675cb7448caacb44 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/cedendahlkim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@32a6aa4cb087ae97e2d62ca8675cb7448caacb44 -
Trigger Event:
release
-
Statement type: