Sistema completo de scraping e API REST para cursos da Universidade do Algarve (UAlg).
- 🚀 Scraper Completo: Extrai informações detalhadas de cursos da UAlg
- 💾 Banco de Dados SQLite: Armazena dados em schema normalizado
- 🌐 API REST com FastAPI: Endpoints para consultar cursos, níveis, escolas e áreas
- 🎨 Interface Web Moderna: Frontend responsivo com visualizações interativas
- 📊 Estatísticas e Gráficos: Dashboard com Chart.js para visualização de dados
- 📄 Download de Documentos: Faz download automático de PDFs e documentos
- 🎓 Extração de Módulos/UCs: Captura unidades curriculares com ECTS, ano, semestre
- 🏷️ Áreas de Conhecimento: Organiza cursos por áreas temáticas
- 🔧 Configurável: Timeouts, retries, user agents personalizáveis
- 📦 Modular: Código organizado e separado em módulos
- ✅ Testes Completos: Cobertura abrangente de testes (46 testes)
- 🔄 Retry Automático: Mecanismo de retry para requisições falhadas
- 📝 Logging Detalhado: Logs para debugging e monitoramento
- ⚡ Rate Limiting: Respeita limites do servidor com delays entre requisições
- 🐳 Docker Ready: Arquitetura completa com Docker Compose para produção
- 🔗 Integração FACODI: Exportação automática para Hugo/FACODI.pt
Pré-requisitos:
- Docker e Docker Compose instalados
Setup rápido:
- Clone o repositório:
git clone https://github.com/Monynha-Softwares/Scrape-UAlg-Courses.git
cd Scrape-UAlg-Courses- Configure variáveis de ambiente:
cp .env.example .env
# Edite .env conforme necessário- (Opcional) Clone o repositório FACODI para integração:
git clone https://github.com/Monynha-Softwares/facodi.pt.git facodi-clone- Inicie os serviços:
make docker-up
# ou
docker-compose up -dServiços disponíveis:
- API: http://localhost:8000
- FACODI: http://localhost:3000 (se facodi-clone existe)
- Execute o scraper (opcional):
make docker-scraper
# ou
docker-compose --profile scraper up scraper- Exporte para Hugo (opcional):
docker-compose run --rm api python scripts/export_to_hugo.py- Python 3.10 ou superior
- pip (gerenciador de pacotes Python)
- Clone o repositório:
git clone https://github.com/Monynha-Softwares/Scrape-UAlg-Courses.git
cd Scrape-UAlg-Courses- Instale as dependências:
make installOu manualmente:
pip install -r requirements.txtPara desenvolvimento, instale dependências adicionais:
make install-devOu manualmente:
pip install -r requirements-dev.txtO sistema utiliza SQLite com as seguintes tabelas normalizadas:
- levels: Níveis de curso (Licenciatura, Mestrado, Doutoramento)
- schools: Escolas/Faculdades
- areas: Áreas de conhecimento
- courses: Informações dos cursos
- modules: Unidades curriculares/módulos
- course_documents: Documentos e PDFs associados
- course_area: Relação many-to-many entre cursos e áreas
- module_course: Relação many-to-many entre módulos e cursos
make init-dbOu com Python:
from src.scrape_ualg import UAlgCourseScraper
scraper = UAlgCourseScraper()
scraper.init_db()Para testar rapidamente o sistema com dados de exemplo:
# 1. Inicializar banco de dados
make init-db
# 2. Popular com dados de demonstração
make demo
# 3. Iniciar servidor API
make run-api
# 4. Acessar interface web em http://localhost:8000/from src.scraper import UAlgScraper
from src.config import Config
# Usando configuração padrão
scraper = UAlgScraper()
courses = scraper.scrape_courses()
for course in courses:
print(f"{course['code']}: {course['name']}")
scraper.close()from src.scrape_ualg import UAlgCourseScraper
# Criar scraper
scraper = UAlgCourseScraper()
# Inicializar banco de dados
scraper.init_db()
# Fazer scraping de todos os cursos (ou limitar com limit=N)
scraper.scrape_all_courses(limit=10)
scraper.close()# Rodar scraper completo
make run-scraper
# Ou diretamente com Python
python -m src.scrape_ualg# Usando make
make run-api
# Ou diretamente com uvicorn
uvicorn src.api:app --reload --host 0.0.0.0 --port 8000A API estará disponível em http://localhost:8000
Acesse http://localhost:8000/ para visualizar a interface web moderna com:
- 📊 Dashboard com estatísticas gerais
- 🔍 Filtros interativos por nível, escola e área
- 📈 Gráficos de distribuição de cursos
- 🎴 Cards de cursos com informações detalhadas
- 📱 Design responsivo
- Interface Web:
http://localhost:8000/ - Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc - API Info (JSON):
http://localhost:8000/api
Listar todos os cursos:
curl http://localhost:8000/coursesObter detalhes de um curso:
curl http://localhost:8000/courses/1Filtrar cursos por nível:
curl "http://localhost:8000/courses?level=Licenciatura"Filtrar cursos por escola:
curl "http://localhost:8000/courses?school=Faculdade%20de%20Ciências"Filtrar cursos por área:
curl "http://localhost:8000/courses?area=Tecnologias%20da%20Informação"Obter estatísticas:
curl http://localhost:8000/statsListar níveis disponíveis:
curl http://localhost:8000/levelsListar escolas:
curl http://localhost:8000/schoolsListar áreas:
curl http://localhost:8000/areasimport requests
# Listar cursos
response = requests.get("http://localhost:8000/courses")
courses = response.json()
# Obter curso específico
response = requests.get("http://localhost:8000/courses/1")
course = response.json()
print(f"Curso: {course['title']}")
print(f"Módulos: {len(course['modules'])}")
print(f"Documentos: {len(course['documents'])}")
# Filtrar por nível
response = requests.get("http://localhost:8000/courses", params={"level": "Mestrado"})
mestrados = response.json()from src.scraper import UAlgScraper
from src.config import Config
# Configuração personalizada
config = Config(
base_url="https://www.ualg.pt",
timeout=60,
max_retries=5
)
scraper = UAlgScraper(config)
courses = scraper.scrape_courses()
scraper.close()Scrape-UAlg-Courses/
├── .github/
│ ├── workflows/
│ │ └── python-app.yml # GitHub Actions CI/CD
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md # Template para reportar bugs
│ │ └── feature_request.md # Template para solicitar features
│ └── PULL_REQUEST_TEMPLATE.md # Template para pull requests
├── docker/
│ ├── api.Dockerfile # Dockerfile para serviço API
│ ├── scraper.Dockerfile # Dockerfile para serviço scraper
│ ├── facodi.Dockerfile # Dockerfile para FACODI/Hugo
│ └── nginx.conf # Configuração nginx para FACODI
├── docs/
│ └── INTEGRATION.md # Guia de integração FACODI
├── src/
│ ├── __init__.py # Inicialização do pacote
│ ├── config.py # Gerenciamento de configuração
│ ├── scraper.py # Scraper básico (original)
│ ├── scrape_ualg.py # Scraper completo com BD
│ └── api.py # API REST FastAPI
├── templates/
│ └── index.html # Interface web moderna
├── scripts/
│ ├── populate_demo_data.py # Popular BD com dados demo
│ └── export_to_hugo.py # Exportar BD para Hugo/FACODI
├── tests/
│ ├── __init__.py
│ ├── test_scraper.py # Testes do scraper básico
│ ├── test_scrape_ualg.py # Testes do scraper completo
│ └── test_api.py # Testes da API
├── data/
│ └── docs/ # Documentos baixados (PDFs)
├── facodi-clone/ # Clone do facodi.pt (opcional)
├── .env.example # Exemplo de variáveis de ambiente
├── .gitignore # Regras do git ignore
├── docker-compose.yml # Orquestração Docker
├── README.md # Este arquivo
├── LICENSE # Licença MIT
├── CONTRIBUTING.md # Guia de contribuição
├── CODE_OF_CONDUCT.md # Código de conduta
├── schema.sql # Schema do banco de dados
├── requirements.txt # Dependências de produção
├── requirements-dev.txt # Dependências de desenvolvimento
└── Makefile # Automação de tarefas comuns
O sistema utiliza Docker Compose com 4 serviços isolados:
-
API Service (ualg-api)
- FastAPI servindo endpoints REST
- Acesso ao SQLite compartilhado
- Interface web de visualização
- Porta: 8000
-
Scraper Service (ualg-scraper)
- Executa scraping sob demanda
- Popula banco de dados SQLite
- Baixa documentos para volume compartilhado
- Perfil:
scraper(não inicia automaticamente)
-
FACODI Frontend (ualg-facodi)
- Site estático Hugo
- Servido via nginx
- Consome API para dados dinâmicos
- Porta: 3000
Construir imagens:
make docker-buildIniciar serviços (API + FACODI):
make docker-upParar serviços:
make docker-downExecutar scraper:
make docker-scraperExportar para Hugo:
docker-compose run --rm api python scripts/export_to_hugo.pyVer logs:
docker-compose logs -f api
docker-compose logs -f scraperPara integração completa com o FACODI.pt, consulte docs/INTEGRATION.md.
Passo a passo:
- Clone o repositório FACODI:
git clone https://github.com/Monynha-Softwares/facodi.pt.git facodi-clone- Execute o scraper para popular dados:
make docker-scraper- Exporte dados para Hugo:
python scripts/export_to_hugo.py- Reconstrua o serviço FACODI:
docker-compose build facodi
docker-compose up -d facodi- Acesse o site em http://localhost:3000
Rodar todos os testes:
make testOu usando pytest diretamente:
pytest tests/ -vCom cobertura:
pytest tests/ -v --cov=src --cov-report=htmlVerificar estilo de código:
make lintFormatar código com black:
make formatRemover arquivos de build e cache:
make cleanO scraper pode ser configurado usando a classe Config ou variáveis de ambiente:
base_url: URL base do site da UAlg (padrão:https://www.ualg.pt)timeout: Timeout de requisição em segundos (padrão: 30)user_agent: String de user agent para requisiçõesmax_retries: Número máximo de tentativas de retry (padrão: 3)request_delay: Delay entre requisições em segundos (padrão: 0.5)
Copie .env.example para .env e configure conforme necessário:
UALG_BASE_URL: URL base para scraping (padrão:https://www.ualg.pt)DB_PATH: Caminho para o banco de dados SQLite (padrão:ualg_courses.db)MAX_RETRIES: Número máximo de tentativas (padrão: 3)REQUEST_DELAY: Delay entre requisições em segundos (padrão: 0.5)REQUEST_TIMEOUT: Timeout de requisições em segundos (padrão: 30)API_PORT: Porta da API (padrão: 8000)FACODI_PORT: Porta do FACODI (padrão: 3000)
| Método | Endpoint | Descrição |
|---|---|---|
| GET | / |
Interface web moderna (HTML) |
| GET | /api |
Informações da API (JSON) |
| GET | /courses |
Listar cursos (com filtros opcionais) |
| GET | /courses/{id} |
Obter detalhes de um curso com módulos, áreas e documentos |
| GET | /levels |
Listar níveis de curso |
| GET | /schools |
Listar escolas/faculdades |
| GET | /areas |
Listar áreas de conhecimento |
| GET | /stats |
Obter estatísticas gerais |
| GET | /api/v1/courses/export |
Exportar todos os cursos em formato Hugo |
| GET | /api/v1/course/{id}/markdown |
Obter curso específico em formato Markdown |
level: Filtrar por nível (ex: "Licenciatura", "Mestrado")school: Filtrar por escolaarea: Filtrar por área de conhecimentolimit: Número máximo de resultados (padrão: 100, máx: 500)offset: Offset para paginação (padrão: 0)
GET /api/v1/courses/export
- Exporta todos os cursos com módulos, documentos e áreas
- Formato JSON adequado para processamento em Hugo
- Inclui timestamp de exportação
GET /api/v1/course/{id}/markdown
- Retorna um curso específico em formato Markdown
- Inclui front matter YAML para Hugo
- Pronto para ser salvo como arquivo
.md
Exemplo:
# Exportar todos os cursos
curl http://localhost:8000/api/v1/courses/export > courses.json
# Obter curso como markdown
curl http://localhost:8000/api/v1/course/1/markdown > curso.mdO scraper implementa delays entre requisições (1.5 segundos) para respeitar o servidor da UAlg. Não modifique estes valores sem considerar o impacto no servidor.
Antes de executar o scraper em produção, verifique e respeite as regras do robots.txt da UAlg.
O scraper usa um User-Agent amigável que identifica a ferramenta. Mantenha isso para facilitar a identificação.
Documentos (PDFs) são baixados para data/docs/. Este diretório é excluído do git via .gitignore.
Contribuições são bem-vindas! Por favor, leia CONTRIBUTING.md para detalhes sobre o código de conduta e o processo para enviar pull requests.
Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para detalhes.
Por favor, leia CODE_OF_CONDUCT.md para detalhes sobre o código de conduta.
Se encontrar problemas ou tiver dúvidas:
- Verifique a página de Issues
- Crie uma nova issue usando o template apropriado
- Forneça o máximo de detalhes possível
- Construído com Requests, Beautiful Soup, FastAPI e Chart.js
- Inspirado pela necessidade de fácil acesso às informações de cursos da UAlg
- Scraper básico de cursos
- Banco de dados SQLite normalizado
- API REST completa
- Download automático de documentos
- Testes completos (46 testes)
- Extração de módulos/UCs com ECTS, ano, semestre
- Extração e organização por áreas de conhecimento
- Interface web moderna e responsiva
- Dashboard com estatísticas e gráficos
- Filtros interativos por nível, escola e área
- Arquitetura Docker Compose com 4 serviços
- Exportação de dados para Hugo/FACODI
- API endpoints para exportação (JSON, Markdown)
- Rate limiting configurável
- Documentação de integração FACODI
- Layouts Hugo para páginas de cursos
- Interface de linha de comando (CLI)
- Exportação adicional (CSV, Excel)
- Suporte para agendamento automático (cron/GitHub Actions)
- Notificações de mudanças em cursos
- Parser de PDFs para extrair planos curriculares detalhados
- CI/CD para build e deploy automático