Just a small set of scripts to improve the workflow for scraping Spanish archive documents from PARES and prepare them for LLMs. Vibe coded so don't expect any miracles.
These can be run directly if you have UV installed.
A small command-line tool for downloading digitized documents from the Spanish archives portal PARES as per-description PDFs.
Given a PARES reference code, description ID, or catalog URL, the script:
- Resolves it to one or more internal description IDs
- Recursively walks “Contains / Contiene” relationships (unless disabled)
- Downloads all available page images via PARES’ viewer
- Assembles them into a single multi-page PDF per description
-
Accepts multiple forms of input:
- Reference codes, e.g.
ES.41091.AGI//PATRONATO,31 - Numeric description IDs, e.g.
122096 - Description URLs, e.g.
https://pares.mcu.es/ParesBusquedas20/catalogo/description/122096 - Search result URLs, e.g.
https://pares.mcu.es/ParesBusquedas20/catalogo/find?...
- Reference codes, e.g.
-
Automatically resolves reference codes to internal description IDs
-
Recursively traverses child descriptions via “Contains / Contiene”
-
Uses Playwright for robust navigation and downloading
-
Retries image downloads with exponential backoff
-
Converts all downloaded JPEGs into a single PDF per description
-
Idempotent and resume-friendly:
- Skips PDFs that already exist
- Skips descriptions with no digitized viewer
-
Filenames are slugified and Windows-safe:
"[{desc_id}] {title}.pdf"
uvx run playwright install chromium # or whatever browser you will use- Save the script as
pares_downloader.py(or similar) and make it executable:
chmod +x pares_downloader.py-
Ensure
uvis installed: -
Install Playwright browsers (once):
uvx run playwright install chromium firefox webkitNo additional pip install step is needed; dependencies are declared in the script header and automatically resolved by uv run.
Basic syntax:
./pares_downloader.py REFERENCE_OR_URL [options]-
referenceOne of:- PARES reference code, e.g.
ES.41091.AGI//PATRONATO,31 - Numeric description ID, e.g.
122096 - Description metadata URL
- Catalog search-results URL
- PARES reference code, e.g.
-
-o, --output-dir PATHBase output directory. Default:./pares_downloads -
--no-recursiveOnly download the given description(s) and do not traverse “Contains” children. -
--browser {firefox,chromium,webkit}Playwright browser engine to use. Default:chromium.
For an input reference (or URL) like:
./pares_downloader.py "ES.41091.AGI//PATRONATO,31"The script:
- Slugifies the input reference and creates a subdirectory inside the output dir:
pares_downloads/
ES.41091.AGI__PATRONATO,31/
[122091] Some description title.pdf
[122092] Child description.pdf
...
- For each description ID it processes:
- Fetches metadata (title, reference number, reference code)
- Builds a filename:
"[{desc_id}] {title}.pdf"(slugified) - Downloads all viewer pages as JPEGs
- Converts to a single multi-page PDF
- If a PDF already exists for a given description ID (based on filename prefix
[{desc_id}]), it is skipped.
./pares_downloader.py "ES.41091.AGI//PATRONATO,31"- Resolves the reference code to its root description ID
- Recursively gathers all “Contains” descriptions
- Creates one PDF per description in:
./pares_downloads/ES.41091.AGI__PATRONATO,31/
./pares_downloader.py "ES.41091.AGI//PATRONATO,31,R.3" --no-recursiveDownloads only that specific description, if digitized.
./pares_downloader.py 122096This bypasses reference resolution and starts traversal from 122096.
./pares_downloader.py "https://pares.mcu.es/ParesBusquedas20/catalogo/description/122096"The script extracts the ID (122096) and proceeds as above.
./pares_downloader.py "https://pares.mcu.es/ParesBusquedas20/catalogo/find?signatura=PATRONATO,31,R.2&signaturaCompleta=1"- Parses all description links in the results table
- Treats each description as a root
- Traverses children (unless
--no-recursiveis used) - Produces multiple PDFs in one run
./pares_downloader.py "ES.41091.AGI//PATRONATO,31" \
--output-dir /path/to/my_archive \
--browser firefoxOutput will be under:
/path/to/my_archive/ES.41091.AGI__PATRONATO,31/
- Only works with documents that have an image viewer in PARES (
#viewerelement). If a description is not digitized (e.g., microfilm only), it is skipped. - Assumes PARES HTML structure and field names remain broadly stable.
- Very large hierarchies or documents with hundreds of pages may take significant time and disk space.