Structured academic data from Bedelías, the student records system of Universidad de la República (Uruguay), which has no public API.
Two components:
- Scraper (
scraper/) — a modular Selenium scraper that logs into Bedelías and extracts course prerequisites (previas), reverse dependencies (posprevias), credits and active courses (vigentes). - REST API (
bedelia/) — a Django REST Framework API that serves the scraped data (careers, courses, prerequisite trees) with filtering and OpenAPI docs.
├── scraper/ # Selenium scraper
│ ├── main.py # Bedelias orchestrator and entry point
│ ├── scraper.py # Base Scraper class
│ ├── config.py # Env-based configuration (ScraperConfig)
│ ├── pages/ # One extractor per Bedelías page
│ │ ├── login.py, previas.py, posprevias.py, credits.py, vigentes.py
│ └── common/ # Navigation and table-pagination helpers
├── bedelia/ # Django REST API
│ ├── api/ # Models, serializers, views, data-load command
│ └── config/ # Settings, URLs, exception handling
├── data/ # Scraped JSON backups
├── eligible_courses.py # Analysis: which courses can I take now?
└── get_libres.py # Analysis: courses that can be taken "libre"
pip install -r requirements.txtCreate a .env file with your Bedelías credentials:
DOCUMENTO=your_document_number
CONTRASENA=your_password
BROWSER=firefox # or chrome
DEBUG=False # True shows the browser window
PAGES=previas,vigentes,posprevias,credits # optional, defaults to allcd scraper
python main.pyExtracted data is written as JSON backups (see data/). On failure, a screenshot.png of the browser is saved to help debugging.
cd bedelia
pip install -r requirements.txt
USE_SQLITE=true python manage.py migrate
USE_SQLITE=true python manage.py load_bedelia_data --clear --verbose
USE_SQLITE=true python manage.py runserverOr with Docker (PostgreSQL included):
cd bedelia
docker compose up --buildSee QUICKSTART.md for the data model and verification steps, and the Postman collection (bedelia_previas_api.postman_collection.json) for example requests.
| Environment variable | Default | Description |
|---|---|---|
USE_SQLITE |
False |
Use SQLite instead of PostgreSQL |
DATABASE_URL |
— | Full database URL (takes precedence) |
DJANGO_SECRET_KEY |
dev-only fallback | Set a real key in production |
DEBUG |
true |
Django debug mode |
ALLOWED_HOSTS |
* |
Comma-separated hosts |
CORS_ALLOWED_ORIGINS |
allow all | Comma-separated origins |