Katalog arboristů
Czech arborists in one catalogue: certified climbers, consultants and companies by region and certificate, refreshed weekly from public registers.
Arboriste
Katalog arboristů (https://katalogarboristu.cz) — a catalogue of Czech arborists: who they are, which certificates they hold and until when, where they work and how to reach them. A sibling of Stromopedie, in the same forest look.
Blazor Web App (interactive server) on .NET 10 with MudBlazor. The data comes from a crawler that runs inside the app once a week; the same crawler is available as a command-line tool.
src/
Arboriste.Crawling/ sources, polite HTTP fetcher with a gzip cache, merging, output files
Arboriste.Crawler/ command-line front end (arboriste-crawler)
Arboriste.Web/ the catalogue web app; hosts the weekly crawl
Sources
| Key | Source | What it gives | How it is read |
|---|---|---|---|
cca |
Český certifikovaný arborista | ~700 certified people: e-mail, phone, website, ČCA / ETW / ETT / VETcert certificates with expiry, EAC number, region | one POST for the whole list, one per region |
szkt |
SZKT – certifikovaní arboristé ETW | ~240 European Tree Workers: phone, e-mail, region | one static table |
spk |
Stromy pod kontrolou | ~350 companies: contacts, contact person, regions, fields of work, certified staff counts, project count | listing + one detail request per entry |
firmy |
Firmy.cz | ~230 companies tagged "arborista": contacts, IČO, GPS, rating, promotional offers | listing pages + schema.org JSON-LD on each detail |
The EAC portal (portal.eac-arboriculture.eu) runs on the same database as the ČCA register, so
its Czech entries already arrive through cca. The regional catalogues idatabaze.cz, netkatalog.cz,
netfirmy.cz and ekatalog.cz refuse the crawler (HTTP 403) and are not used.
Running locally
dotnet run --project src/Arboriste.Crawler # crawl into ./data (about 12 minutes, cached for 7 days)
dotnet run --project src/Arboriste.Web # http://localhost:5171, reads ./data
In Development the web app reads ../../data and does not crawl on its own
(appsettings.Development.json). Crawler options: --source cca,firmy, --refresh, --out <dir>,
--firmy-tags arborista,rizikove-kaceni, --verbose; merge re-merges the raw files without crawling.
/— catalogue with search and filters (region, certificate, service, company or person); the filter lives in the query string, so a filtered list can be shared/arborista/{id}— detail: certificates with validity, certified people, services, contacts, sources/?zobrazeni=mapa— the same catalogue on a map (pins for arborists with an address; clicking a region filters)/o-katalogu— where the data comes from, how fresh it is, how to have an entry removed/health—{ "status", "version", "name", "entries": { "catalog", "map", "admin" } }, unauthenticated/admin— one password (Admin:Password), a month-long cookie: overview of the catalogue and the last crawl, Ceníky (price research) and Logy (live log events and the daily log files)
Data folder
App_Data in the container (/opt/arboriste/data on the VPS), ./data locally — git-ignored,
it holds personal contacts:
| Path | Content |
|---|---|
raw/<source>.json |
records exactly as each source describes them |
arborists.json |
merged catalogue the web app serves |
arborists.csv |
the same, flattened for Excel |
crawl-state.json |
outcome of the last crawl (per-source counts and errors) |
arboriste.db |
the arborists' own entries, edits for review, takeover requests, sign-in links (hashed), outbox, audit trail |
raw/self.json |
the arborists' entries as a source for the merge, written on every publish |
prices.json, prices/pages/ |
price research results and the text of every page it read |
geocode.json |
Mapy.com geocoding answers per address, kept between crawls |
cache/ |
downloaded pages, gzipped, reused for 3 days (7 from the CLI) |
logs/ |
daily rolling log files of the web app, 30 days |
keys/ |
ASP.NET data-protection keys |
The weekly crawl
CrawlScheduler runs the crawl inside the web app every 7 days at 3 a.m. Prague time
(Crawler:Interval, Crawler:Hour), and right away on a fresh install with no catalogue.
It costs no extra container or cron job; while it runs the app uses a few tens of MB more.
- One request at a time per site, 1.5 s apart (2.5 s for firmy.cz); the sources run side by side.
- A site that answers 403/429 or with a CAPTCHA page stops that source. The crawler does not disguise itself or work around a block; the source's previous data is kept, and an interrupted run never overwrites an earlier complete result.
/healthturnsDegradedwhen the catalogue is older than three intervals.
Maps
- Base map: Mapy.com tiles through
/api/tiles/{z}/{x}/{y}, which adds the key (Mapy:ApiKey) on the server, the same way as boudakaci.cz. Without a key, Development falls back to OpenStreetMap and Production shows no base map (/health→Degraded). Leaflet 1.9.4 is vendored inwwwroot/vendor/leaflet. - Region and district boundaries:
src/Arboriste.Crawling/Data/territory.geojson— 14 regions and 77 districts from ČÚZK INSPIRE Územní správní jednotky (CC BY 4.0), simplified to ~200 m (430 kB, 117 kB gzipped). Rebuild withnode tools/build-territory.mjs. The crawler uses it to put a seat into its district and region; the web serves it at/data/territory.geojson. - Geocoding: with a key, addresses without coordinates (mostly Stromy pod kontrolou) are geocoded once with Mapy.com;
answers are kept in
geocode.jsonin the data folder. The CLI reads the key fromARBORISTE_MAPY_KEY. - Pins are rounded to ~100 m: an address of a sole trader is often a home.
Arborists manage their own entries
- Taking over an entry (
/spravovat/{id}, linked from every detail): a one-time link (30 minutes) goes to an e-mail the entry already lists — it comes from the registers and directories, not from the claimant, so reaching that inbox is the proof. The addresses are shown masked. Nobody reachable that way asks the admin instead (their own e-mail is confirmed first); the admin checks them, e.g. by phone, and hands the entry over. - Signing in (
/prihlaseni): by e-mail link only; no passwords are stored. Links are stored as hashes, used once, and at most four go to one address per hour. - Editing (
/muj-zaznam/{id}): name, IČO, contacts, address, districts (okresy) the arborist works in, services, description. Edits wait for the admin (/admin/zaznamyshows only the changed fields); hiding the entry takes effect at once. Certificates are not editable — they come from the registers only. - New entries (
/pridat): after confirming the e-mail; published at once. The form points to existing entries with the same IČO, e-mail or phone and suggests taking one over instead. - How it joins the catalogue: the profiles live in
arboriste.db(SQLite) and are written as the sourceself(raw/self.json) next to the crawled ones; every publish merges the catalogue again. A profile joins crawled records only through the references it took over (LinkedSources), never through shared contacts, so a new entry cannot take over someone else's by quoting their IČO. What the arborist filled in wins; the entry keeps its URL. - E-mail: Resend (
Email:ResendApiKey,Email:From). Until it is configured every message waits in the admin outbox, where a link can be copied and passed on by hand.
Price research (admin)
/admin/ceniky (or arboriste-crawler prices locally) visits the website of every provider, reads the home page,
pages and PDFs called ceník / ceny / sazebník (else the service pages), and pulls out every amount in Kč with its unit,
VAT note and a guessed service. Each price keeps the raw block of text it came from, and the whole text read from each
page is kept too (/admin/ceniky/text/{key}), so every number can be checked against its source. Results:
prices.json and prices/pages/ in the data folder; CSV at /admin/ceniky.csv. Directory profiles
(nejremeslnici.cz, …) are skipped; hosting firewalls that answer 401/403 are reported as blocked, not worked around.
This is research for the admin only — nothing of it is shown on the public site.
Merging
Records are grouped when they share an IČO, an e-mail, a phone number, a website domain (not free-mail or social domains), or — for people — the same name without academic titles. A group with a company record or several different people becomes a company with its certified people listed inside.
Deployment
Azure Pipelines → Docker image → VPS behind the shared nginx, the same way as Stromopedie. See docs/deployment.md.
Changelog
Changelog
0.7.2 — 2026-10-08
- Changed: the footer links to Stromopedie and TreeMap use their new addresses stromopedie.cz and treemap.cz.
0.7.1 — 2026-10-05
- Changed: the service filter sits right below the region, and the certificate list folds away; it opens when a link already selects certificates, and the folded header shows how many are selected.
0.7.0 — 2026-09-30
- Added: the catalogue is listed in the TomLabs app store (apps.tomlabs.cz).
- Added: visit statistics through Google Analytics, only after consent in the cookie bar; a "Cookies" link in the footer changes the choice and O katalogu explains what is stored.
0.6.1 — 2026-09-30
- Fixed: contacts no longer hide after a few searches; the per-address limit on revealed contacts is gone.
0.6.0 — 2026-09-30
- Changed: the catalogue is listed in a random order that changes with every visit, so nobody is permanently on top; a search still puts names starting with the searched text first.
- Added: phones and e-mails are no longer part of the page source. They appear after the first mouse movement, touch or key press, and one network address sees the contacts of at most 120 arborists an hour and 400 a day.
- Added: the footer links to the sibling tree tools Stromopedie and TreeMap.
0.5.0 — 2026-09-29
- Changed: the catalogue is called Katalog arboristů and moves to katalogarboristu.cz; arboriste.tomlabs.xyz is retired.
- Added: arborists can take over their entry — a one-time link goes to an e-mail the entry already lists; without access to one, they ask and the admin hands the entry over.
- Added: editing of one's own entry — contacts, address, districts (okresy) worked in, services, description; edits are published after the admin approves them, hiding the entry takes effect at once.
- Added: new entries by arborists, published after the e-mail is confirmed, with a hint when a similar entry exists.
- Added: the detail shows who manages an entry and the districts on the map; "Pro arboristy" in the menu.
- Added: /admin/zaznamy — edits to approve with only the changed fields, takeover requests, managed entries, the outbox (sign-in links wait there until Resend is set up) and a history of changes.
0.4.0 — 2026-09-26
- Added: an admin section at /admin behind one password — an overview of the catalogue and the last crawl, and a Logs page with live events and the daily log files.
- Added: price research — visits every provider's website, finds price lists (pages and PDFs) and shows each price
with its service, unit and VAT note next to the raw text it was read from, a summary per service (min, median, max)
and a CSV export. Started from the admin; also
arboriste-crawler prices. - Changed: websites answering in windows-1250 are read correctly.
0.3.2 — 2026-09-26
- Changed: the home page heading is now simply "Katalog arboristů".
0.3.1 — 2026-09-25
- Changed: regions on the maps are clearly visible — warm yellow fill with a dark border and a readable name, the district of the seat in a stronger amber, other regions faint; the detail lists the regions as chips under the map; larger zoom buttons for touch.
- Added: after an upgrade the app merges the catalogue again from the data on disk, so new districts, regions and geocoded addresses show up right after a deploy instead of after the next weekly crawl.
0.3.0 — 2026-09-25
- Added: a map view of the catalogue on Mapy.com tiles — a pin per arborist with an address (green with a valid certificate), the current filters apply, and clicking a region filters to it.
- Added: "Kde působí" on the detail page — a map with the regions the arborist works in and the seat.
- Added: every arborist with coordinates gets the district (okres) of its seat, and its region when no source named one, from ČÚZK boundaries; more arborists now show up under a region filter.
- Added: addresses without coordinates are geocoded with Mapy.com once and remembered.
- Fixed: a map that fails to draw no longer breaks the page.
0.2.0 — 2026-09-25
- Added: the catalogue web app — search, filters by region, certificate, service and company or person, a detail page per arborist with certificate validity, certified people, services and contacts, and an "O katalogu" page on sources and removal requests. Light, dark and system theme; works on a phone.
- Added: the crawl runs inside the web app once a week at night, and right away on a fresh install.
- Added:
GET /healthwith the version and the state of the catalogue. - Added: Docker image, Azure Pipelines and VPS deploy script for arboriste.tomlabs.xyz.
- Changed: downloaded pages are cached gzipped and expired pages are deleted.
- Changed: websites differing only in http/https or www are listed once.
- Removed: the idatabaze.cz, netkatalog.cz, netfirmy.cz and ekatalog.cz sources, which refuse the crawler.
0.1.0 — 2026-09-25
- Added: crawler that collects Czech arborists from the ČCA register (including EAC certificates), the SZKT list of European Tree Workers, Stromy pod kontrolou, firmy.cz and the regional catalogues idatabaze.cz, netkatalog.cz, netfirmy.cz and ekatalog.cz.
- Added: merging of the same arborist or company across sources by IČO, e-mail, phone, website and name.
- Added: output as
data/arborists.json(full detail) anddata/arborists.csv(for Excel).