# 02 - Projeto Scraper Java A pasta irmão `scrapper` contém uma aplicação autónoma em puro Java com a responsabilidade de raspar (scrapping) a informação dos clubes, jogos e tabelas. ## Ficheiros Críticos O projeto está implementado em `src/main/java/org/example/`. Destacam-se: - `Main.java`: Onde o projeto arranca. Configura a ligação com Firebase, cria a Realtime DB reference e também executa as ações principais (ex. extrair info de clubes). - `StandingsScraper.java`: Classe responsável pela extração das Tabelas Classificativas (Standings) e lista de jogos (Jornadas) baseando-se num endpoint JSON fornecido pela AFAVCD. - `PlayersScraper.java`: Esqueleto preparado para iterar pela lista de plantéis das equipas. - Diretório `models/`: Classes de modelos Java que refletem a estrutura exata do que será enviado ao Firebase. ## Tecnologias Usadas 1. **JSoup**: Utilizado para enviar HTTP requests a URLs tradicionais e efetuar o parsing de documentos HTML usando CSS Selectors (quando a informação não é fornecida via JSON). 2. **GSON (Google JSON)**: Utilizado quando a associação fornece endpoints JSON. O Gson pega nas "Strings" JSON devolvidas pela API e converte para objetos (models) Java, facilitando o acesso às propriedades. 3. **Firebase Admin SDK**: Ao contrário do Android (que usa Auth regular de cliente), o Scraper tem privilégios de Admin. Utiliza a "chave de serviço" de Firebase (vulgarmente no ficheiro `service-account.json` que deve manter-se sempre fora do controlo de versões, via `.gitignore`). 4. **Gradle**: O ciclo de build e os pacotes são geridos pelo Gradle (usando sintaxe `build.gradle.kts`). ## O Fluxo Padrão do Scraper 1. A função `main` carrega o Firebase Options, passando as credenciais para obter acesso total à base de dados de Firebase. 2. Invocam-se os Scrapers. Por exemplo, `StandingsScraper.scrapeAndSync()`. 3. O Scraper descarrega o payload (JSON ou HTML). 4. O Scraper itera os elementos (Equipas, Jogos). Cria uma instância da classe Model relevante (ex: `TeamStanding.java`). 5. A referência Firebase é chamada (e.g. `ref.child("Senior").child("standings")`) e o objeto é passado por `setValueAsync()`. ## Notas de Evolução - *Limites de Rate*: Quando o projeto aumentar a sua abrangência (extrair todos os jogadores para todas as equipas), deve-se implementar delays (`Thread.sleep()`) para prevenir que o servidor que está a sofrer o scraping bloqueie o nosso IP. - *Tipagem Ficheiros Models*: Os atributos nas classes `models/` têm de bater certo com os declarados na App Android. Qualquer refactoring a nomes de atributos, deverá ser feito em ambos os projetos sob pena de a App Android apresentar UI sem dados (`null`).