This repository extracts structured data from Frontex SIR PDFs.
fetch_sir_zip_urls.py: scrapes Frontex metadata and updateszip_urls.txt+sir_documents.jsonl.process_sir_zips.sh: downloads ZIP/PDF sources intorawdata/and prepares PDFs inpdfs/<batch>/.extract_sir_pdf_gemini.py: sends PDFs to Gemini and writes outputs toanalysis_output/.prompts/: extraction prompts (default:prompts/extract_sir.txt).docs/: supporting documentation.rawdata/,pdfs/,analysis_output/: data artifacts (large files tracked with Git LFS where applicable).
Use the local virtual environment:
source .venv/bin/activate
export GEMINI_API_KEY="..."Core commands:
python3 fetch_sir_zip_urls.py --dry-runchecks new URLs/metadata without writing../process_sir_zips.sh zip_urls.txtdownloads and extracts PDFs.python3 extract_sir_pdf_gemini.py pdfs --output-dir analysis_outputruns full extraction.python3 extract_sir_pdf_gemini.py pdfs/pad-2025-00419/file.pdf --output-dir analysis_outputprocesses one PDF.python3 extract_sir_pdf_gemini.py pdfs --no-skip-existingforces reprocessing.
For analysis and synthesis of tabular outputs, prefer DuckDB over ad-hoc scripts when working on *.csv and *.jsonl.
Examples:
duckdb :memory: "SELECT count(*) FROM 'sir_documents.jsonl';"duckdb :memory: "SELECT substr(publication_date,1,4) AS year, count(*) FROM 'sir_documents.jsonl' GROUP BY 1 ORDER BY 1;"duckdb :memory: "SELECT sir_id, dead_confirmed FROM 'analysis_output/summary.csv' ORDER BY dead_confirmed DESC NULLS LAST LIMIT 20;"
- Python: PEP 8, 4-space indentation, explicit type hints, clear function names (
snake_case). - Bash:
set -euo pipefail, defensive checks, lowercasesnake_casevars. - Keep scripts idempotent when possible (
--dry-run, skip-existing behavior). - Name outputs predictably:
<pdf_stem>.extracted.json, per-foldersummary.csv,summary_totals.json.
There is no formal automated test suite yet. Validate changes with:
python3 fetch_sir_zip_urls.py --dry-run- A small extraction run on one folder or one PDF
- Manual inspection of
analysis_output/*/summary.csvandsummary_totals.json
When changing parsing/schema logic, include at least one before/after output example in your PR notes.
Follow the existing history style: Conventional Commit prefixes such as feat: and docs: (e.g., feat: add prompt-path option).
PRs should include:
- What changed and why
- Commands run for validation
- Data impact (files/fields affected, reprocessing needed or not)
- Any API cost/runtime implications
- Never commit secrets; use
GEMINI_API_KEYvia environment variables. - Treat
rawdata/,pdfs/, and generated outputs as large artifacts; avoid unnecessary churn in tracked binaries.