memories-crawl 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memories_crawl-0.2.0/.claude/memory/MEMORY.md +4 -0
- memories_crawl-0.2.0/.claude/memory/project_memories_crawl.md +16 -0
- memories_crawl-0.2.0/.claude/memory/project_overijssel_blocker.md +45 -0
- memories_crawl-0.2.0/.claude/settings.local.json +12 -0
- memories_crawl-0.2.0/.github/workflows/ci.yml +44 -0
- memories_crawl-0.2.0/.github/workflows/publish.yml +31 -0
- memories_crawl-0.2.0/.gitignore +9 -0
- memories_crawl-0.2.0/.python-version +1 -0
- memories_crawl-0.2.0/CLAUDE.md +376 -0
- memories_crawl-0.2.0/GUIDE.md +64 -0
- memories_crawl-0.2.0/PKG-INFO +446 -0
- memories_crawl-0.2.0/README.md +422 -0
- memories_crawl-0.2.0/pyproject.toml +57 -0
- memories_crawl-0.2.0/src/memories_crawl/__init__.py +0 -0
- memories_crawl-0.2.0/src/memories_crawl/__main__.py +5 -0
- memories_crawl-0.2.0/src/memories_crawl/bhic.py +386 -0
- memories_crawl-0.2.0/src/memories_crawl/cli.py +176 -0
- memories_crawl-0.2.0/src/memories_crawl/drentsarchief.py +248 -0
- memories_crawl-0.2.0/src/memories_crawl/friesland.py +350 -0
- memories_crawl-0.2.0/src/memories_crawl/gelderland.py +664 -0
- memories_crawl-0.2.0/src/memories_crawl/limburg.py +556 -0
- memories_crawl-0.2.0/src/memories_crawl/nationaalarchief.py +367 -0
- memories_crawl-0.2.0/src/memories_crawl/noordholland.py +663 -0
- memories_crawl-0.2.0/src/memories_crawl/overijssel.py +375 -0
- memories_crawl-0.2.0/src/memories_crawl/utrechtsarchief.py +598 -0
- memories_crawl-0.2.0/src/memories_crawl/zeeland.py +658 -0
- memories_crawl-0.2.0/tests/test_smoke.py +65 -0
- memories_crawl-0.2.0/uv.lock +318 -0
- memories_crawl-0.2.0/websites.md +203 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Memory Index
|
|
2
|
+
|
|
3
|
+
- [Project: Memories van Successie pipeline](project_memories_crawl.md) — all 8 archives complete including Overijssel (implemented April 2026)
|
|
4
|
+
- [Overijssel MAIS token extraction — SOLVED](project_overijssel_blocker.md) — complete kantoor minr map, per-page token approach, corrected image URL format
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Memories van Successie pipeline
|
|
3
|
+
description: Python pipeline to download Dutch succession registers from 8 regional archives; all archives implemented
|
|
4
|
+
type: project
|
|
5
|
+
---
|
|
6
|
+
Downloads all *Memories van Successie* (Dutch inheritance registers, 1806–1927) from 8 Dutch regional archives. Scans are saved with `metadata.json` sidecars.
|
|
7
|
+
|
|
8
|
+
**Status** (as of 2026-04-14):
|
|
9
|
+
- ✅ Open Archieven (5 archives: BHIC, Zeeuws Archief, HUA, Gelders, NHA) — 3-step pipeline via OAI-PMH XML dumps
|
|
10
|
+
- ✅ Nationaal Archief (Zuid-Holland, access 3.06.05) — Drupal viewer scrape
|
|
11
|
+
- ✅ Drents Archief (Drenthe) — Memorix REST API
|
|
12
|
+
- ✅ Overijssel (HCO) — Playwright-based MAIS token extraction, implemented April 2026
|
|
13
|
+
|
|
14
|
+
**Why:** Complete download for genealogical/historical research purposes.
|
|
15
|
+
|
|
16
|
+
**How to apply:** `python/overijssel.py` is fully implemented. Run with `uv run python main.py overijssel`. Requires `playwright install chromium` after `uv sync`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Overijssel MAIS token extraction — SOLVED
|
|
3
|
+
description: How MAIS per-page auth tokens are extracted and what the complete kantoor minr mapping is
|
|
4
|
+
type: project
|
|
5
|
+
---
|
|
6
|
+
The Historisch Centrum Overijssel (HCO) uses the MAIS Internet viewer system. Images at `preserve2.archieven.nl` require three per-page auth tokens: `miahd`, `rdt`, `open`. These are **per-page**: each scan page has its own unique `miahd` and `open`.
|
|
7
|
+
|
|
8
|
+
**SOLVED April 2026** — `python/overijssel.py` is fully implemented.
|
|
9
|
+
|
|
10
|
+
## How token extraction works
|
|
11
|
+
|
|
12
|
+
1. Navigate (Playwright/Chromium) to the MAIS inv3 page for the kantoor minr:
|
|
13
|
+
`https://collectieoverijssel.nl/collectie/archieven/?mivast=20&mizig=210&miadt=141&miaet=1&micode=0136.4&minr={minr}&milang=nl&miview=inv3`
|
|
14
|
+
2. The page auto-loads PHPSESSID + mi_sessid cookies (WordPress + MAIS).
|
|
15
|
+
3. Collect all `a[onclick*="stk3"]` links — each is one invnr volume.
|
|
16
|
+
4. For each: call `mi_inv3_toggle_stk(args)` via `page.evaluate()`.
|
|
17
|
+
5. Wait ~1.5s, harvest `img[src*="/fonc-hco/"]` from the DOM.
|
|
18
|
+
6. Parse `invnr`, `page`, `miahd`, `rdt`, `open` from each src URL.
|
|
19
|
+
|
|
20
|
+
## Image URL format (corrected — original stub was wrong)
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
https://preserve2.archieven.nl/mi-20/fonc-hco/0136.4/{invnr}/
|
|
24
|
+
NL-ZlHCO_0136.4_{invnr}_{page:04d}.jpg
|
|
25
|
+
?miadt=141&miahd={miahd}&mivast=20&rdt={rdt}&open={open}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Note the `{invnr}/` subdirectory — the original stub was missing this.
|
|
29
|
+
|
|
30
|
+
## Complete KANTOOR_MINR mapping (verified April 2026)
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
KANTOOR_MINR = {
|
|
34
|
+
"Almelo": 2227676,
|
|
35
|
+
"Deventer": 2227950,
|
|
36
|
+
"Enschede": 2228207,
|
|
37
|
+
"Goor": 2228335, # original stub had wrong names: Hardenberg, Oldenzaal, Overige
|
|
38
|
+
"Kampen": 2228502,
|
|
39
|
+
"Ommen": 2228649,
|
|
40
|
+
"Raalte": 2228752,
|
|
41
|
+
"Steenwijk": 2228889,
|
|
42
|
+
"Vollenhove": 2228980,
|
|
43
|
+
"Zwolle": 2229046,
|
|
44
|
+
}
|
|
45
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(git:*)",
|
|
5
|
+
"mcp__playwright__browser_network_requests",
|
|
6
|
+
"mcp__playwright__browser_evaluate",
|
|
7
|
+
"mcp__playwright__browser_wait_for",
|
|
8
|
+
"mcp__playwright__browser_navigate",
|
|
9
|
+
"WebFetch(domain:www.bhic.nl)"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
check:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.12", "3.14"]
|
|
19
|
+
fail-fast: false
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
enable-cache: true
|
|
29
|
+
cache-dependency-glob: "uv.lock"
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv sync --all-groups
|
|
33
|
+
|
|
34
|
+
- name: Lint with ruff
|
|
35
|
+
run: uv run ruff check
|
|
36
|
+
|
|
37
|
+
- name: Check formatting with ruff
|
|
38
|
+
run: uv run ruff format --check
|
|
39
|
+
|
|
40
|
+
- name: Run smoke tests
|
|
41
|
+
run: uv run pytest -v --tb=short
|
|
42
|
+
|
|
43
|
+
- name: Build package
|
|
44
|
+
run: uv build
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
enable-cache: true
|
|
24
|
+
|
|
25
|
+
- name: Build
|
|
26
|
+
run: uv build
|
|
27
|
+
|
|
28
|
+
- name: Publish
|
|
29
|
+
env:
|
|
30
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
31
|
+
run: uv publish
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# CLAUDE.md – Memories van Successie Pipeline
|
|
2
|
+
|
|
3
|
+
## What this project does
|
|
4
|
+
|
|
5
|
+
Downloads all surviving *Memories van Successie* (Dutch succession/inheritance registers, 1806–1927) from ten regional Dutch archives. Each scan is saved alongside a `metadata.json` sidecar.
|
|
6
|
+
|
|
7
|
+
## How to run
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv run memories-crawl friesland # Friesland (Tresoar / AlleFriezen, Memorix API)
|
|
11
|
+
uv run memories-crawl nationaalarchief # Zuid-Holland (Nationaal Archief 3.06.05)
|
|
12
|
+
uv run memories-crawl drentsarchief # Drenthe (Memorix API)
|
|
13
|
+
uv run memories-crawl bhic # Noord-Brabant (BHIC Memorix API)
|
|
14
|
+
uv run memories-crawl overijssel # Overijssel (HCO) – requires Playwright
|
|
15
|
+
uv run memories-crawl utrechtsarchief # Utrecht (Het Utrechts Archief) – requires Playwright
|
|
16
|
+
uv run memories-crawl limburg # Limburg (RHCL, archieven.nl MAIS) – requires Playwright
|
|
17
|
+
uv run memories-crawl noordholland # Noord-Holland (Noord-Hollands Archief) – requires Playwright
|
|
18
|
+
uv run memories-crawl zeeland # Zeeland (Zeeuws Archief) – requires Playwright
|
|
19
|
+
uv run memories-crawl gelderland # Gelderland (Gelders Archief) – requires Playwright
|
|
20
|
+
uv run memories-crawl all
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## File map
|
|
24
|
+
|
|
25
|
+
| File | Purpose |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `src/memories_crawl/cli.py` | CLI dispatcher |
|
|
28
|
+
| `src/memories_crawl/nationaalarchief.py` | Zuid-Holland: scrape viewer pages, download via UUID |
|
|
29
|
+
| `src/memories_crawl/drentsarchief.py` | Drenthe: Memorix REST API, deed→asset chain |
|
|
30
|
+
| `src/memories_crawl/bhic.py` | Noord-Brabant (BHIC): Memorix REST API, register→asset chain |
|
|
31
|
+
| `src/memories_crawl/overijssel.py` | Overijssel: Playwright-based MAIS token extraction |
|
|
32
|
+
| `src/memories_crawl/utrechtsarchief.py` | Utrecht: Playwright-based MAIS stk3 inline strip extraction |
|
|
33
|
+
| `src/memories_crawl/limburg.py` | Limburg (RHCL): Playwright on archieven.nl, strip Volgende-step |
|
|
34
|
+
| `src/memories_crawl/noordholland.py` | Noord-Holland: Playwright-based MAIS stk3 inline strip extraction |
|
|
35
|
+
| `src/memories_crawl/zeeland.py` | Zeeland: Playwright-based MAIS hybrid (inv3 discovery + inv2 strip harvest) |
|
|
36
|
+
| `src/memories_crawl/friesland.py` | Friesland: Tresoar / AlleFriezen Memorix REST API, register→deed→person chain |
|
|
37
|
+
| `src/memories_crawl/gelderland.py` | Gelderland: Playwright-based MAIS, one micode per kantoor (21 codes), strip auto-loads on inv2 minr |
|
|
38
|
+
|
|
39
|
+
## Exclusion rule
|
|
40
|
+
|
|
41
|
+
**Always exclude Tafel V-bis.** In all parsers and filters, skip any record whose SourceType contains "tafel" or "v-bis" (case-insensitive). The Nationaal Archief Tafel V-bis items are in a different inventory section (outside 2276–2357) and are excluded by range.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Overijssel (HCO) – MAIS token extraction
|
|
46
|
+
|
|
47
|
+
First-time setup: `uv sync && playwright install chromium`
|
|
48
|
+
|
|
49
|
+
The HCO uses a MAIS Internet viewer. Each scan page requires unique per-page tokens
|
|
50
|
+
(`miahd`, `rdt`, `open`). The implementation in `python/overijssel.py`:
|
|
51
|
+
|
|
52
|
+
1. Opens the MAIS inv3 page in headless Chromium to establish the session.
|
|
53
|
+
2. Clicks each invnr-item stk3 link via `mi_inv3_toggle_stk(...)`.
|
|
54
|
+
3. Harvests `img[src*="/fonc-hco/"]` from the DOM to get per-page tokens.
|
|
55
|
+
|
|
56
|
+
**Image URL format:**
|
|
57
|
+
```
|
|
58
|
+
https://preserve2.archieven.nl/mi-20/fonc-hco/0136.4/{invnr}/
|
|
59
|
+
NL-ZlHCO_0136.4_{invnr}_{page:04d}.jpg
|
|
60
|
+
?miadt=141&miahd={miahd}&mivast=20&rdt={rdt}&open={token}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Kantoor minr values** (verified April 2026):
|
|
64
|
+
|
|
65
|
+
| Kantoor | minr |
|
|
66
|
+
|------------|---------|
|
|
67
|
+
| Almelo | 2227676 |
|
|
68
|
+
| Deventer | 2227950 |
|
|
69
|
+
| Enschede | 2228207 |
|
|
70
|
+
| Goor | 2228335 |
|
|
71
|
+
| Kampen | 2228502 |
|
|
72
|
+
| Ommen | 2228649 |
|
|
73
|
+
| Raalte | 2228752 |
|
|
74
|
+
| Steenwijk | 2228889 |
|
|
75
|
+
| Vollenhove | 2228980 |
|
|
76
|
+
| Zwolle | 2229046 |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Pipeline status (verified 2026-04-24)
|
|
81
|
+
|
|
82
|
+
Each pipeline was live-tested against the real APIs and servers.
|
|
83
|
+
|
|
84
|
+
| Pipeline | API/Server | End-to-end | Notes |
|
|
85
|
+
|---|---|---|---|
|
|
86
|
+
| **friesland** | ✅ | ⚠️ not yet tested | Tresoar / AlleFriezen Memorix REST API. 1,107 registers, ~238k persons. Deed-level assets with .jp2 downloads. Person→deed join via deed_id. Output: scans/friesland/{kantoor}/{invnr}/{person}/. |
|
|
87
|
+
| **nationaalarchief** | ✅ | ✅ | 70 scans downloaded from invnr 2276 in 60s (174 MB). EAD XML parses correctly, drupal-settings-json extraction works, `service.archief.nl` download works. |
|
|
88
|
+
| **drentsarchief** | ✅ | ⚠️ slow start | API returns ~106k deeds. Pipeline must paginate ~1064 pages to collect all deed IDs **before** any download begins (~5 min). Once collection finishes, downloads work (8.3 MB/scan tested). |
|
|
89
|
+
| **overijssel** | ✅ | ⚠️ slow first run | Playwright + Chromium work. Almelo has 256 stk3 items → ~1825 pages of tokens; collecting tokens takes ~6 min per kantoor. Token results are cached in `scans/overijssel/tokens_minr_{minr}.json` — reruns skip Playwright entirely. |
|
|
90
|
+
| **utrechtsarchief** | ✅ | ⚠️ slow first run | Playwright + Chromium. Uses stk3 inline toggle (same approach as Overijssel). Amersfoort verified: 66,615 pages from 211 invnrs across 2 subsections (~12 min harvest). Token results cached per subsection — reruns skip Playwright. 11 kantoren configured. |
|
|
91
|
+
| **limburg** | ✅ | ✅ verified | archieven.nl MAIS (miadt=38, mivast=0). Two codes: 07.D03 (1818-1900, 111 digitized of 1,314, ~104k scans, by place) and 07.D08 (1901-1927, 42 digitized of 460, ~7k scans, by kantoor). End-to-end smoke-tested: invnr 1 (Amby) → 527 pages; invnr 491 (Gennep) → 207 pages. Inventory + tokens cached per code/invnr; reruns skip Playwright. Image format is `format=large` PNG (714×1024); see module docstring for trade-off vs. IIPSrv full-res JP2 path. |
|
|
92
|
+
| **noordholland** | ✅ | ⚠️ not yet tested | noord-hollandsarchief.nl MAIS (miadt=236, mivast=236, micode=178). Uses stk3 inline toggle (same approach as Overijssel/Utrecht). Kantoor sections discovered dynamically from inv2 tree. Tokens cached per section minr; reruns skip Playwright. Image server: preserve-nha.archieven.nl/mi-0/fonc-nha/178/. |
|
|
93
|
+
| **zeeland** | ✅ | ✅ verified | Zeeuws Archief MAIS (miadt=239, mivast=239, micode=398). Hybrid approach: inv3 tree for discovery (kantoor→sub-section→invnr with h_scan markers), inv2 minr pages for strip harvesting (auto-loads strip, force-load all chunks via mi_strip_store.populate()). Goes verified: 990 digitized invnrs of 1,109, invnr 1 → 327 pages, invnr 2 → 373 pages. Image server: preserve-zaf.archieven.nl/mi-239/fonc-zaf/398/. Downloads at `format=large` PNG (673×1024). Filenames include segment slug for uniqueness (e.g. `1-1_0001.jpg`). Tokens cached per kantoor in `tokens_minr_{minr}.json`. |
|
|
94
|
+
| **gelderland** | ✅ | ✅ verified | Gelders Archief MAIS (miadt=37, mivast=37). 21 kantoren, each with its own micode (0021–0037, 0092, 0221–0223). Per-kantoor pipeline: inv2 → pick "Register IV" minr (filter "Tafel VI / V-bis") → inv3 → swapinv-expand period sub-sections → collect leaf invnrs with `h_scan` markers and `^\d+\s` text. Per-invnr token harvest = navigate to inv2&minr=…, force-load strip via `mi_strip_store.populate()`, harvest `img[src*="fonc-gea"]`. Borculo (0022) verified end-to-end: 49 digitized invnrs, invnr 1 → 38 pages, full-size 1024×858 PNG (~570 KB/page). Image server: preserve2.archieven.nl/mi-37/fonc-gea/{code}/. Filenames `{invnr}-{page:04d}.jpg`. Inventory + tokens cached per code; reruns skip Playwright. |
|
|
95
|
+
|
|
96
|
+
**Setup reminder**: Chromium must be installed with `uv run playwright install chromium` (not bare `playwright install chromium`).
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Technical notes
|
|
101
|
+
|
|
102
|
+
### Nationaal Archief scan extraction
|
|
103
|
+
|
|
104
|
+
Scans are in a `<script data-drupal-selector="drupal-settings-json">` JSON blob. Parse `settings["viewer"]["response"]["scans"]`. Each scan has `{"id": UUID, "label": "NL-HaNA_...", "default": {"url": "https://service.archief.nl/api/file/v1/default/{UUID}"}}`. Download via `default.url`.
|
|
105
|
+
|
|
106
|
+
### Drents Archief API
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Base: https://webservices.memorix.nl/genealogy
|
|
110
|
+
Key: a85387a2-fdb2-44d0-8209-3635e59c537e
|
|
111
|
+
Person search: GET /person?q=*:*&fq=search_s_deed_type_title:"Successiememories"&rows=100&page=N
|
|
112
|
+
Deed detail: GET /deed/{deed_id}
|
|
113
|
+
Full image: asset[].download (e.g. https://images.memorix.nl/dre/download/fullsize/{uuid}.jpg)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### BHIC (Noord-Brabant) API
|
|
117
|
+
|
|
118
|
+
Same Memorix backend, **different tenant key**, and scans live at the **register**
|
|
119
|
+
level (one register = one bound book), not at the deed level.
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Base: https://webservices.memorix.nl/genealogy
|
|
123
|
+
Key: 24c66d08-da4a-4d60-917f-5942681dcaa1
|
|
124
|
+
Register list: GET /register?q=*:*&fq=search_s_type_title:"memorie van successie"&rows=100&page=N
|
|
125
|
+
Assets: GET /asset?fq=register_id:{register_id}&rows=100&page=N
|
|
126
|
+
Deeds: GET /deed?fq=register_id:{register_id}&rows=100&page=N
|
|
127
|
+
Persons: GET /person?fq=register_id:{register_id}&rows=100&page=N
|
|
128
|
+
Full image: asset[].download (https://images.memorix.nl/bhic/download/fullsize/{file_id}.jpg)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
1,896 registers total. Code prefixes are `036.03.01..19` (Memories van successie,
|
|
132
|
+
kantoor X) plus `021.13` (Memories van successie Brabant). Tafel V-bis is not
|
|
133
|
+
indexed at BHIC, but `_is_tafel()` filters defensively just in case.
|
|
134
|
+
|
|
135
|
+
### Friesland (Tresoar / AlleFriezen) – Memorix REST API
|
|
136
|
+
|
|
137
|
+
Tresoar's *Memories van Successie* are served via AlleFriezen, which runs the
|
|
138
|
+
same Memorix Genealogy REST API as Drenthe and BHIC.
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
Base: https://webservices.memorix.nl/genealogy
|
|
142
|
+
Key: aa030ec4-12d0-4dc0-afaf-b65fd6128b39
|
|
143
|
+
Tenant: frl
|
|
144
|
+
Register list: GET /register?q=*:*&fq=search_s_type_title:"Memories van successie"&rows=100&page=N
|
|
145
|
+
Deeds: GET /deed?fq=register_id:{register_id}&rows=100&page=N
|
|
146
|
+
Persons: GET /person?fq=register_id:{register_id}&rows=100&page=N
|
|
147
|
+
Full image: asset[].download → https://tresoar-images.memorix.nl/frl/download/fullsize/{path}.jp2
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
1,107 registers total, ~238,576 persons. Entity types: `mvs` (register),
|
|
151
|
+
`mvs_a` (deed/akte), `mvs_a_persoon` (person). One person per deed (the
|
|
152
|
+
"overledene"). Deeds embed their asset references directly (`has_assets: "deed"`,
|
|
153
|
+
`asset[].download`).
|
|
154
|
+
|
|
155
|
+
Tafel V-bis is not present in the Tresoar collection (0 results).
|
|
156
|
+
|
|
157
|
+
**Person metadata** includes `person_display_name`, `voornaam`, `tussenvoegsel`,
|
|
158
|
+
`geslachtsnaam`, `patroniem`, `datum_overlijden`, `plaats` (overlijdensplaats),
|
|
159
|
+
`plaats_wonen`, `geslacht`.
|
|
160
|
+
|
|
161
|
+
Deed metadata includes `nummer` (aktenummer), `plaats`, `diversen`
|
|
162
|
+
(free-text notes with filmnummer, estate details, family relations).
|
|
163
|
+
|
|
164
|
+
**Image format**: JPEG 2000 (`.jp2`). No format conversion is done;
|
|
165
|
+
convert with `magick mogrify -format jpg *.jp2` if needed.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
Folder layout
|
|
169
|
+
─────────────
|
|
170
|
+
scans/friesland/{kantoor}/{invnr}/{person_slug}/
|
|
171
|
+
{NNNN}.jp2 – sequentially numbered scan pages
|
|
172
|
+
metadata.json – per-person info (name, date of death, …)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Kantoor is extracted from the register `naam` field (e.g. "Sneek" from
|
|
176
|
+
"Memories kantoor Sneek").
|
|
177
|
+
|
|
178
|
+
**Resume**: `friesland_progress.csv` tracks completed registers. Existing
|
|
179
|
+
per-person directories (with `metadata.json`) are skipped on reruns.
|
|
180
|
+
|
|
181
|
+
### Limburg (RHCL) – archieven.nl MAIS
|
|
182
|
+
|
|
183
|
+
Two archive codes hold all Memories van Successie at RHCL:
|
|
184
|
+
|
|
185
|
+
| Code | Period | Total invnrs | Digitized | Organised by |
|
|
186
|
+
|--------|----------------|--------------|-----------|--------------|
|
|
187
|
+
| 07.D03 | 1818-1900 (1905) | 1,314 | 111 | Plaats (place of death) |
|
|
188
|
+
| 07.D08 | 1901-1927 | 460 | 42 | Kantoor |
|
|
189
|
+
|
|
190
|
+
07.D08 also contains a sibling section "Tafels 5bis" (minr 1014481) which is
|
|
191
|
+
**excluded** per the project-wide Tafel V-bis rule. The scraper drills into
|
|
192
|
+
07.D08's MvS-only sub-section (parent minr 1014062), so the tafel branch is
|
|
193
|
+
never visited.
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
inv2 root: https://www.archieven.nl/nl/zoeken
|
|
197
|
+
?mivast=0&mizig=210&miadt=38&micode={code}&miview=inv2
|
|
198
|
+
per-invnr page: …same…&minr={minr} (strip auto-loads)
|
|
199
|
+
image URL: https://preserve3.archieven.nl/mi-0/fonc-rhcl/{code}/{invnr}/
|
|
200
|
+
NL-MtHCL_{code}_{invnr}_{page:04d}.jpg
|
|
201
|
+
?format=large&miadt=38&miahd={miahd}&mivast=0&rdt={rdt}&open={token}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Pagination quirks:
|
|
205
|
+
- The root inv2 page renders only ~100 leaf nodes at a time, with a
|
|
206
|
+
``Records N t/m M`` toggle per remaining batch driven by
|
|
207
|
+
``mi_inv3_swapinv(...)``. The scraper clicks every batch in-page until none
|
|
208
|
+
remain.
|
|
209
|
+
- The per-invnr strip exposes only 25 thumbnails initially; the rest are
|
|
210
|
+
loaded by clicking the ``.snext`` (Volgende) arrow. The scraper steps the
|
|
211
|
+
arrow until the ``.snavuit`` (disabled) class appears.
|
|
212
|
+
|
|
213
|
+
Image format: ``format=large`` returns a 714×1024 PNG (~700 KB-1.2 MB per
|
|
214
|
+
page). The archival 2090×3000 JPEG is only available via the IIPSrv zoomify
|
|
215
|
+
tile server (``iipsrv12.fcgi?FIF=cache/fonc-rhcl/{hash}.jp2&CVT=jpeg``), but
|
|
216
|
+
the ``{invnr,page} → JP2 hash`` map is only exposed inside each scan's
|
|
217
|
+
embed-viewer HTML, so reaching full-res would require an extra viewer load
|
|
218
|
+
per scan (~110 k loads). See module docstring for details.
|
|
219
|
+
|
|
220
|
+
Caches:
|
|
221
|
+
- ``scans/limburg/inventory_{code}.json`` – list of digitized invnrs
|
|
222
|
+
- ``scans/limburg/tokens_{code}_{invnr}.json`` – per-page tokens for one register
|
|
223
|
+
|
|
224
|
+
Both caches are sufficient for the download phase; rerunning skips Playwright
|
|
225
|
+
entirely once they exist.
|
|
226
|
+
|
|
227
|
+
### Noord-Holland (NHA) – noord-hollandsarchief.nl MAIS
|
|
228
|
+
|
|
229
|
+
Archive 178 holds all *Memories van Successie* for the province of Noord-Holland.
|
|
230
|
+
The inventory is organized by kantoor (tax office), discovered dynamically from
|
|
231
|
+
the inv2 tree via Playwright.
|
|
232
|
+
|
|
233
|
+
**Approach**: Same stk3 inline toggle pattern as Overijssel and Utrecht.
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
inv2 root: https://noord-hollandsarchief.nl/bronnen/archieven
|
|
237
|
+
?mivast=236&mizig=210&miadt=236&micode=178&miview=inv2
|
|
238
|
+
inv3 (kantoor): …same…&miaet=1&micode=178&minr={minr}&milang=nl&miview=inv3
|
|
239
|
+
image URL: https://preserve-nha.archieven.nl/mi-0/fonc-nha/178/{invnr}/
|
|
240
|
+
NL-HlmNHA_178_{invnr}_{page:04d}.jpg
|
|
241
|
+
?miadt=236&miahd={miahd}&mivast=0&rdt={rdt}&open={token}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Image format**: Remove `?format=thumb` from thumbnail URLs to get full-size.
|
|
245
|
+
Note that the preserve URL uses `mivast=0` (not 236), same pattern as Limburg.
|
|
246
|
+
|
|
247
|
+
**Caches**:
|
|
248
|
+
- ``scans/noordholland/sections.json`` – discovered kantoor sections
|
|
249
|
+
- ``scans/noordholland/tokens_{minr}.json`` – per-page tokens for one kantoor section
|
|
250
|
+
- ``scans/noordholland/tokens_{minr}_partial.json`` – incremental save (crash-resilient)
|
|
251
|
+
|
|
252
|
+
**Resume**: ``scans/noordholland/done.txt`` tracks completed kantoor sections.
|
|
253
|
+
Partial token caches allow resuming interrupted harvest runs.
|
|
254
|
+
|
|
255
|
+
### Zeeland (Zeeuws Archief) – MAIS token extraction
|
|
256
|
+
|
|
257
|
+
First-time setup: ``uv sync && playwright install chromium``
|
|
258
|
+
|
|
259
|
+
The Zeeuws Archief runs its own MAIS instance on the zeeuwsarchief.nl domain. The
|
|
260
|
+
scraper takes a **hybrid approach**:
|
|
261
|
+
|
|
262
|
+
1. **Discovery** – Navigates to the inv3 tree view for each kantoor minr, expands
|
|
263
|
+
all sub-sections via swapinv clicks, then harvests inventarisnummer minr values
|
|
264
|
+
(and their texts) from stk3 onclick handlers. Digitized items are those whose
|
|
265
|
+
tree node carries an `h_scan.gif` marker. Tafel V-bis filtered by text.
|
|
266
|
+
|
|
267
|
+
2. **Token harvest** – Navigates to each invnr's inv2 minr page. The strip viewer
|
|
268
|
+
auto-loads on this page. All strip chunks are force-loaded via
|
|
269
|
+
``mi_strip_store.populate()``, then thumbnail ``<img>`` elements with
|
|
270
|
+
``src*="fonc-zaf"`` are harvested from the DOM.
|
|
271
|
+
|
|
272
|
+
3. **Download** – Thumbnails have ``?format=thumb``; replacing with ``?format=large``
|
|
273
|
+
yields 673×1024 PNG. The preserve server is ``preserve-zaf.archieven.nl/mi-239/``.
|
|
274
|
+
|
|
275
|
+
**Image URL format:**
|
|
276
|
+
```
|
|
277
|
+
https://preserve-zaf.archieven.nl/mi-239/fonc-zaf/398/{invnr}/
|
|
278
|
+
NL-MdbZA_398_{invnr}_{slug}_{page:04d}.jpg
|
|
279
|
+
?format=large&miadt=239&miahd={miahd}&mivast=239&rdt={rdt}&open={token}
|
|
280
|
+
```
|
|
281
|
+
Some images omit the ``{slug}_`` component (e.g. ``NL-MdbZA_398_1_0001.jpg``). The
|
|
282
|
+
slug provides uniqueness when the same trailing page number appears in multiple
|
|
283
|
+
scan segments within one register.
|
|
284
|
+
|
|
285
|
+
**Kantoren** (9 total, discovered dynamically):
|
|
286
|
+
|
|
287
|
+
| Kantoor | minr | Digitized invnrs | Total invnrs |
|
|
288
|
+
|-------------|-----------|------------------|--------------|
|
|
289
|
+
| Goes | 33439946 | 990 | 1,109 |
|
|
290
|
+
| Hulst | 33439947 | TBD | TBD |
|
|
291
|
+
| Colijnsplaat/Kortgene | 33439948 | TBD | TBD |
|
|
292
|
+
| Middelburg | 33439949 | TBD | TBD |
|
|
293
|
+
| Oostburg | 33439950 | TBD | TBD |
|
|
294
|
+
| Tholen | 33439951 | TBD | TBD |
|
|
295
|
+
| Veere | 33439952 | TBD | TBD |
|
|
296
|
+
| Vlissingen | 33439953 | TBD | TBD |
|
|
297
|
+
| Zierikzee | 33439954 | TBD | TBD |
|
|
298
|
+
|
|
299
|
+
**Caches**:
|
|
300
|
+
- ``scans/zeeland/kantoren.json`` – discovered kantoor entries with minr values
|
|
301
|
+
- ``scans/zeeland/tokens_minr_{minr}.json`` – per-page tokens for one kantoor
|
|
302
|
+
- ``scans/zeeland/tokens_minr_{minr}_partial.json`` – incremental save (crash-resilient)
|
|
303
|
+
|
|
304
|
+
**Resume**: ``scans/zeeland/done.txt`` tracks completed kantoren.
|
|
305
|
+
Partial token caches allow resuming interrupted harvest runs.
|
|
306
|
+
|
|
307
|
+
**Smoke test** (2026-05-11): Goes invnr 1 → 327 pages, invnr 2 → 373 pages.
|
|
308
|
+
Downloads at ``format=large`` PNG (673×1024, ~300KB–950KB per page).
|
|
309
|
+
|
|
310
|
+
### Gelderland (Gelders Archief) – per-kantoor MAIS code
|
|
311
|
+
|
|
312
|
+
First-time setup: ``uv sync && uv run playwright install chromium``
|
|
313
|
+
|
|
314
|
+
Unlike every other MAIS instance in the project, the Gelders Archief gives
|
|
315
|
+
**each kantoor its own archief-code**. Twenty-one kantoren are hardcoded in
|
|
316
|
+
``KANTOREN`` (resolved 2026-05-11 from the kantoor permalinks listed at
|
|
317
|
+
``https://www.geldersarchief.nl/informatie/zoekhulp/997-memories-van-successie``):
|
|
318
|
+
|
|
319
|
+
| Kantoor | Code | Kantoor | Code | Kantoor | Code |
|
|
320
|
+
|-------------|-------|-------------|-------|-------------|-------|
|
|
321
|
+
| Arnhem | 0021 | Elst | 0028 | Tiel | 0026 |
|
|
322
|
+
| Apeldoorn | 0092 | Groenlo | 0029 | Wageningen | 0036 |
|
|
323
|
+
| Borculo | 0022 | Harderwijk | 0030 | Winterswijk | 0223 |
|
|
324
|
+
| Culemborg | 0023 | Hattem | 0031 | Zaltbommel | 0037 |
|
|
325
|
+
| Doesburg | 0024 | Lochem | 0032 | Zevenaar | 0221 |
|
|
326
|
+
| Druten | 0025 | Nijkerk | 0033 | Zutphen | 0222 |
|
|
327
|
+
| Elburg | 0027 | Nijmegen | 0034 | | |
|
|
328
|
+
| | | Terborg | 0035 | | |
|
|
329
|
+
|
|
330
|
+
Inside each kantoor's inv2 tree there are normally two top-level openinv items:
|
|
331
|
+
|
|
332
|
+
1. *Register IV, akten van het recht van successie en van overgang …* – the
|
|
333
|
+
actual Memories van Successie. Scraper keeps this.
|
|
334
|
+
2. *Tafel VI, alfabetische index … en Tafel V-bis, …* – Tafel V-bis is
|
|
335
|
+
excluded per the project-wide rule, so we filter any top-level openinv
|
|
336
|
+
whose text contains "tafel", "v-bis", or "5bis".
|
|
337
|
+
|
|
338
|
+
Below Register IV the records are grouped by 5-year periods ("Akten,
|
|
339
|
+
1818-1825.", "Akten, 1826-1830.", …). Each period eventually contains the
|
|
340
|
+
leaf inventarisnummers ("1 1818", "140 1895 eerste kwartaal", …).
|
|
341
|
+
Digitized leaves carry an ``h_scan.gif`` icon in their tree row; leaves whose
|
|
342
|
+
text starts with ``^\d+\s`` and that have the marker are kept.
|
|
343
|
+
|
|
344
|
+
Scans are accessed by navigating to each leaf invnr's inv2 page; the
|
|
345
|
+
thumbnail strip auto-loads (25 thumbs initially) and remaining chunks are
|
|
346
|
+
force-loaded via ``mi_strip_store[…].populate()`` exactly as the Zeeland
|
|
347
|
+
scraper does.
|
|
348
|
+
|
|
349
|
+
**Image URL format:**
|
|
350
|
+
```
|
|
351
|
+
https://preserve2.archieven.nl/mi-37/fonc-gea/{code}/{invnr}/
|
|
352
|
+
{invnr}-{page:04d}.jp2
|
|
353
|
+
?format=large&miadt=37&miahd={miahd}&mivast=37&rdt={rdt}&open={token}
|
|
354
|
+
```
|
|
355
|
+
Note the unusual filename convention: the file is named after the
|
|
356
|
+
inventarisnummer (``{invnr}-{page:04d}.jp2``), not a fixed archive
|
|
357
|
+
identifier. The path itself also contains ``{invnr}`` between the code and
|
|
358
|
+
filename. ``?format=large`` returns a 1024-pixel-tall PNG (~500 KB/page);
|
|
359
|
+
the full-resolution JP2 is only reachable via IIPSrv tile-server requests
|
|
360
|
+
that would require an extra viewer load per page (~tens of thousands of
|
|
361
|
+
extra requests project-wide), so ``format=large`` is the practical maximum
|
|
362
|
+
here.
|
|
363
|
+
|
|
364
|
+
**Caches**:
|
|
365
|
+
- ``scans/gelderland/inventory_{code}.json`` – discovered leaf invnrs for one
|
|
366
|
+
kantoor: ``[{invnr, text, minr, hasScan}, …]``
|
|
367
|
+
- ``scans/gelderland/tokens_{code}.json`` – per-page tokens for one kantoor
|
|
368
|
+
- ``scans/gelderland/tokens_{code}_partial.json`` – incremental save written
|
|
369
|
+
every 25 invnrs so a crash mid-harvest doesn't lose work
|
|
370
|
+
|
|
371
|
+
**Resume**: ``scans/gelderland/done.txt`` tracks completed kantoor codes.
|
|
372
|
+
|
|
373
|
+
**Smoke test** (2026-05-11): Borculo (code 0022) end-to-end – 49 digitized
|
|
374
|
+
invnrs discovered, invnr 1 ("1 1818 eerste halfjaar") → 38 pages, full-size
|
|
375
|
+
download = 1024×858 PNG (~570 KB). Tafel-only kantoor sections are
|
|
376
|
+
automatically skipped at the Register-IV selection step.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Guide: How this project downloads Memories van Successie
|
|
2
|
+
|
|
3
|
+
## What are we downloading?
|
|
4
|
+
|
|
5
|
+
When someone died in the Netherlands between 1806 and 1927, their heirs had to register the estate with the local tax office. These registers — *Memories van Successie* — list the deceased's name, date and place of death, their heirs, and what the estate was worth. They are a unique source for family history.
|
|
6
|
+
|
|
7
|
+
About 150,000 register volumes survive across ten regional archives. Each volume contains anything from a few dozen to over a thousand handwritten pages. This project downloads all of them — scans and metadata — so researchers can work with them offline.
|
|
8
|
+
|
|
9
|
+
## Why not just browse the websites?
|
|
10
|
+
|
|
11
|
+
The scans exist online. But every archive uses a different website, a different viewer, and a different way of organising its data. There is no "download all" button. Some archives let you view one page at a time through a clunky in-browser viewer. Others hide the images behind JavaScript that only runs when you click through their interface. None of them expose a simple list of links you can hand to a download tool.
|
|
12
|
+
|
|
13
|
+
That is what these scripts do: they automate the clicking, the waiting, the page-stepping, and the URL-collecting — tasks a human could do by hand, but which would take months of repetitive work.
|
|
14
|
+
|
|
15
|
+
## The two kinds of archive software
|
|
16
|
+
|
|
17
|
+
Most Dutch archives run one of two commercial platforms to serve their scans online.
|
|
18
|
+
|
|
19
|
+
**MAIS** (by De Ree) is a tree-based inventory viewer. You expand folders in a hierarchy — archive → section → register → page — and a thumbnail strip loads at the bottom. The full-size images are protected by per-page tokens that expire. The browser gets these tokens from JavaScript code that runs when you click on a thumbnail; you cannot simply copy a URL and come back later. Six of the ten archives use MAIS. Because MAIS is configurable, each archive's tree has a slightly different shape, so each needs its own script — but the underlying trick (launch a headless browser, simulate clicks, harvest the URLs that appear) is the same.
|
|
20
|
+
|
|
21
|
+
**Memorix** (by Picturae) is a REST API behind a search portal. You send a query (e.g. "give me all registers labelled *memorie van successie*") and get back structured data — metadata, file URLs, people linked to deeds. This is much easier to work with than MAIS because the data is machine-readable from the start. Three of the ten archives (Drenthe, BHIC, Tresoar) expose their collections through Memorix.
|
|
22
|
+
|
|
23
|
+
The Nationaal Archief uses neither system and has its own custom viewer.
|
|
24
|
+
|
|
25
|
+
## Why three Memorix pipelines look different
|
|
26
|
+
|
|
27
|
+
Although Drenthe, BHIC, and Tresoar all run Memorix, they attach scans at different levels of the data model:
|
|
28
|
+
|
|
29
|
+
- **Drenthe** puts scans on individual *deeds* (one entry in a register). Each dead person gets their own folder.
|
|
30
|
+
- **BHIC** puts scans on the *register* (the bound book). All pages of the book download into one folder, and a separate `deeds.json` sidecar lists every entry inside it with names and dates.
|
|
31
|
+
- **Tresoar** (Friesland) also puts scans at the deed level, but the deeds are linked to *persons*, so the pipeline creates one folder per person. The images are JPEG 2000 files rather than standard JPEGs.
|
|
32
|
+
|
|
33
|
+
These differences exist because each archive chose its own digitisation workflow — some scanned whole books, others scanned individual entries, and the metadata linking was done differently each time.
|
|
34
|
+
|
|
35
|
+
## The Playwright part
|
|
36
|
+
|
|
37
|
+
For the six MAIS archives, the scripts use a tool called Playwright. It launches a real Chromium browser (the same engine inside Google Chrome) but invisibly, without a window. The script tells this browser: "go to this page, wait for the tree to load, click every expand button, then collect every image URL you see." The gathered URLs — each containing a fresh authentication token — are saved to disk so the slow browser step only runs once. After that, a standard downloader fetches all the images.
|
|
38
|
+
|
|
39
|
+
## What you end up with
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
scans/
|
|
43
|
+
├── friesland/Sneek/1234/Pieter_Janssen_abc123/
|
|
44
|
+
│ ├── metadata.json
|
|
45
|
+
│ └── 0001.jp2 … 0024.jp2
|
|
46
|
+
├── bhic/Den_Bosch/deel_5678/
|
|
47
|
+
│ ├── metadata.json
|
|
48
|
+
│ ├── deeds.json
|
|
49
|
+
│ └── DenBosch_044_0001.jpg …
|
|
50
|
+
├── overijssel/Zwolle/9012/
|
|
51
|
+
│ ├── metadata.json
|
|
52
|
+
│ └── 0000.jpg … 0127.jpg
|
|
53
|
+
…
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Every folder gets a `metadata.json` sidecar with the archive name, inventory number, kantoor (tax district), name of the deceased (where available), and the original web URL. From there you can browse, search, or feed the collection into other tools.
|
|
57
|
+
|
|
58
|
+
## What this project does not do
|
|
59
|
+
|
|
60
|
+
It does not transcribe handwriting, index names, or turn the scans into searchable text. It only downloads what the archives already published online — just in a form you can actually work with.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
The scripts live in `src/memories_crawl/`. Each file covers one archive. Run `memories-crawl all` to download everything, or pick individual archives with e.g. `memories-crawl bhic`. See `README.md` for the full command list and setup instructions.
|